Add IKVM.Reflection
authorMarek Safar <marek.safar@gmail.com>
Thu, 16 Dec 2010 09:29:45 +0000 (09:29 +0000)
committerMarek Safar <marek.safar@gmail.com>
Thu, 16 Dec 2010 09:29:45 +0000 (09:29 +0000)
87 files changed:
mcs/class/IKVM.Reflection/AmbiguousMatchException.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Assembly.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/AssemblyName.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/BadImageFormatException.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Binder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/ConstructorInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/CustomAttributeData.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/CustomAttributeNamedArgument.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/CustomAttributeTypedArgument.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/AssemblyBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/ConstructorBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/CustomAttributeBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/EnumBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/Enums.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/EventBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/FieldBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/ILGenerator.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/MethodBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/ModuleBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/OpCode.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/OpCodes.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/ParameterBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/PropertyBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/SignatureHelper.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/Tokens.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Emit/TypeBuilder.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Enums.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/EventInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/ExceptionHandlingClause.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/FieldInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/FieldSignature.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Fusion.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/GenericWrappers.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/IKVM.Reflection.csproj [new file with mode: 0644]
mcs/class/IKVM.Reflection/Impl/CryptoConvert.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Impl/CryptoHack.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Impl/ITypeOwner.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Impl/MdbWriter.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Impl/PdbWriter.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Impl/SymbolSupport.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/InterfaceMapping.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/LocalVariableInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/ManifestResourceInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MarshalSpec.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MemberInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Metadata/CliHeader.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Metadata/MetadataRW.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Metadata/Tables.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MethodBase.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MethodBody.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MethodImplMap.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MethodInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/MethodSignature.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Module.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/ParameterInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/ParameterModifier.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Properties/AssemblyInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/PropertyInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/PropertySignature.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/AssemblyReader.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/ByteReader.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/EventInfoImpl.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/Field.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/GenericTypeParameter.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/MetadataReader.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/Method.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/ModuleReader.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/PEReader.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/PropertyInfoImpl.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/ResourceModule.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Reader/TypeDefImpl.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Signature.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/StandAloneMethodSig.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/StrongNameKeyPair.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Type.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/TypeNameParser.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Universe.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Util.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/ByteBuffer.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/Heaps.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/MetadataWriter.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/ModuleWriter.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/PEWriter.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/ResourceSection.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/TextSection.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/Writer/VersionInfo.cs [new file with mode: 0644]
mcs/class/IKVM.Reflection/reflect.build [new file with mode: 0644]

diff --git a/mcs/class/IKVM.Reflection/AmbiguousMatchException.cs b/mcs/class/IKVM.Reflection/AmbiguousMatchException.cs
new file mode 100644 (file)
index 0000000..121d69f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection
+{
+       [Serializable]
+       public sealed class AmbiguousMatchException : Exception
+       {
+               public AmbiguousMatchException()
+               {
+               }
+
+               public AmbiguousMatchException(string message)
+                       : base(message)
+               {
+               }
+
+               public AmbiguousMatchException(string message, Exception inner)
+                       : base(message, inner)
+               {
+               }
+
+               private AmbiguousMatchException(SerializationInfo info, StreamingContext context)
+                       : base(info, context)
+               {
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Assembly.cs b/mcs/class/IKVM.Reflection/Assembly.cs
new file mode 100644 (file)
index 0000000..8e547ae
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+
+namespace IKVM.Reflection
+{
+       public abstract class Assembly : ICustomAttributeProvider
+       {
+               internal readonly Universe universe;
+
+               internal Assembly(Universe universe)
+               {
+                       this.universe = universe;
+               }
+
+               public abstract Type[] GetTypes();
+               public abstract string FullName { get; }
+               public abstract AssemblyName GetName();
+               public abstract string ImageRuntimeVersion { get; }
+               public abstract Module ManifestModule { get; }
+               public abstract MethodInfo EntryPoint { get; }
+               public abstract string Location { get; }
+               public abstract AssemblyName[] GetReferencedAssemblies();
+               public abstract Module[] GetModules(bool getResourceModules);
+               public abstract Module[] GetLoadedModules(bool getResourceModules);
+               public abstract Module GetModule(string name);
+               public abstract string[] GetManifestResourceNames();
+               public abstract ManifestResourceInfo GetManifestResourceInfo(string resourceName);
+               public abstract System.IO.Stream GetManifestResourceStream(string resourceName);
+
+               internal abstract Type GetTypeImpl(string typeName);
+
+               public Module[] GetModules()
+               {
+                       return GetModules(true);
+               }
+
+               public Module[] GetLoadedModules()
+               {
+                       return GetLoadedModules(true);
+               }
+
+               public AssemblyName GetName(bool copiedName)
+               {
+                       return GetName();
+               }
+
+               public bool ReflectionOnly
+               {
+                       get { return true; }
+               }
+
+               public Type[] GetExportedTypes()
+               {
+                       List<Type> list = new List<Type>();
+                       foreach (Type type in GetTypes())
+                       {
+                               if (type.IsVisible)
+                               {
+                                       list.Add(type);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public Type GetType(string typeName)
+               {
+                       return GetType(typeName, false);
+               }
+
+               public Type GetType(string typeName, bool throwOnError)
+               {
+                       TypeNameParser parser = TypeNameParser.Parse(typeName, throwOnError);
+                       if (parser.Error)
+                       {
+                               return null;
+                       }
+                       if (parser.AssemblyName != null)
+                       {
+                               if (throwOnError)
+                               {
+                                       throw new ArgumentException("Type names passed to Assembly.GetType() must not specify an assembly.");
+                               }
+                               else
+                               {
+                                       return null;
+                               }
+                       }
+                       return parser.Expand(GetTypeImpl(parser.FirstNamePart), this, throwOnError, typeName);
+               }
+
+               public virtual Module LoadModule(string moduleName, byte[] rawModule)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public Module LoadModule(string moduleName, byte[] rawModule, byte[] rawSymbolStore)
+               {
+                       return LoadModule(moduleName, rawModule);
+               }
+
+               public bool IsDefined(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+               }
+
+               public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+               }
+
+               public static string CreateQualifiedName(string assemblyName, string typeName)
+               {
+                       return assemblyName == null ? typeName : typeName + ", " + assemblyName;
+               }
+
+               public static Assembly GetAssembly(Type type)
+               {
+                       return type.Assembly;
+               }
+
+               public string CodeBase
+               {
+                       get
+                       {
+                               string path = this.Location.Replace(System.IO.Path.DirectorySeparatorChar, '/');
+                               if (!path.StartsWith("/"))
+                               {
+                                       path = "/" + path;
+                               }
+                               return "file://" + path;
+                       }
+               }
+
+               internal abstract IList<CustomAttributeData> GetCustomAttributesData(Type attributeType);
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/AssemblyName.cs b/mcs/class/IKVM.Reflection/AssemblyName.cs
new file mode 100644 (file)
index 0000000..e89e80d
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Globalization;
+using System.Configuration.Assemblies;
+using System.IO;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+       public sealed class AssemblyName : ICloneable
+       {
+               private readonly System.Reflection.AssemblyName name;
+               private string culture;
+
+               private AssemblyName(System.Reflection.AssemblyName name, string culture)
+               {
+                       this.name = name;
+                       this.culture = culture;
+               }
+
+               public AssemblyName()
+               {
+                       name = new System.Reflection.AssemblyName();
+               }
+
+               public AssemblyName(string assemblyName)
+               {
+                       name = new System.Reflection.AssemblyName(assemblyName);
+               }
+
+               public override string ToString()
+               {
+                       string str = name.ToString();
+                       if (culture != null)
+                       {
+                               str = str.Replace("Culture=neutral", "Culture=" + culture);
+                       }
+                       return str;
+               }
+
+               public string Name
+               {
+                       get { return name.Name; }
+                       set { name.Name = value; }
+               }
+
+               public CultureInfo CultureInfo
+               {
+                       get { return name.CultureInfo; }
+                       set
+                       {
+                               name.CultureInfo = value;
+                               culture = null;
+                       }
+               }
+
+               internal string Culture
+               {
+                       set
+                       {
+                               culture = value;
+                               name.CultureInfo = CultureInfo.InvariantCulture;
+                       }
+               }
+
+               public Version Version
+               {
+                       get { return name.Version; }
+                       set { name.Version = value; }
+               }
+
+               public StrongNameKeyPair KeyPair
+               {
+                       get { return name.KeyPair == null ?  null : new StrongNameKeyPair(name.KeyPair); }
+                       set { name.KeyPair = value == null ? null : value.keyPair; }
+               }
+
+               public string CodeBase
+               {
+                       get { return name.CodeBase; }
+                       set { name.CodeBase = value; }
+               }
+
+               public ProcessorArchitecture ProcessorArchitecture
+               {
+                       get { return (ProcessorArchitecture)name.ProcessorArchitecture; }
+                       set { name.ProcessorArchitecture = (System.Reflection.ProcessorArchitecture)value; }
+               }
+
+               public AssemblyNameFlags Flags
+               {
+                       get { return (AssemblyNameFlags)name.Flags; }
+                       set { name.Flags = (System.Reflection.AssemblyNameFlags)value; }
+               }
+
+               public AssemblyVersionCompatibility VersionCompatibility
+               {
+                       get { return name.VersionCompatibility; }
+                       set { name.VersionCompatibility = value; }
+               }
+
+               public byte[] GetPublicKey()
+               {
+                       return name.GetPublicKey();
+               }
+
+               public void SetPublicKey(byte[] publicKey)
+               {
+                       name.SetPublicKey(publicKey);
+               }
+
+               public byte[] GetPublicKeyToken()
+               {
+                       return name.GetPublicKeyToken();
+               }
+
+               public void SetPublicKeyToken(byte[] publicKeyToken)
+               {
+                       name.SetPublicKeyToken(publicKeyToken);
+               }
+
+               public AssemblyHashAlgorithm HashAlgorithm
+               {
+                       get { return name.HashAlgorithm; }
+                       set { name.HashAlgorithm = value; }
+               }
+
+               public string FullName
+               {
+                       get
+                       {
+                               string str = name.FullName;
+                               if (culture != null)
+                               {
+                                       str = str.Replace("Culture=neutral", "Culture=" + culture);
+                               }
+                               return str;
+                       }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       AssemblyName other = obj as AssemblyName;
+                       return other != null && other.FullName == this.FullName;
+               }
+
+               public override int GetHashCode()
+               {
+                       return FullName.GetHashCode();
+               }
+
+               public object Clone()
+               {
+                       return new AssemblyName((System.Reflection.AssemblyName)name.Clone(), culture);
+               }
+
+               public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition)
+               {
+                       return System.Reflection.AssemblyName.ReferenceMatchesDefinition(reference.name, definition.name);
+               }
+
+               public static AssemblyName GetAssemblyName(string path)
+               {
+                       try
+                       {
+                               path = Path.GetFullPath(path);
+                               using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+                               {
+                                       ModuleReader module = new ModuleReader(null, null, fs, path);
+                                       if (module.Assembly == null)
+                                       {
+                                               throw new BadImageFormatException("Module does not contain a manifest");
+                                       }
+                                       return module.Assembly.GetName();
+                               }
+                       }
+                       catch (IOException x)
+                       {
+                               throw new FileNotFoundException(x.Message, x);
+                       }
+                       catch (UnauthorizedAccessException x)
+                       {
+                               throw new FileNotFoundException(x.Message, x);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/BadImageFormatException.cs b/mcs/class/IKVM.Reflection/BadImageFormatException.cs
new file mode 100644 (file)
index 0000000..330f983
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection
+{
+       [Serializable]
+       public sealed class BadImageFormatException : Exception
+       {
+               public BadImageFormatException()
+               {
+               }
+
+               public BadImageFormatException(string message)
+                       : base(message)
+               {
+               }
+
+               public BadImageFormatException(string message, Exception inner)
+                       : base(message, inner)
+               {
+               }
+
+               private BadImageFormatException(SerializationInfo info, StreamingContext context)
+                       : base(info, context)
+               {
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Binder.cs b/mcs/class/IKVM.Reflection/Binder.cs
new file mode 100644 (file)
index 0000000..1307f00
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Globalization;
+
+namespace IKVM.Reflection
+{
+       public abstract class Binder
+       {
+               protected Binder()
+               {
+                       throw new NotSupportedException();
+               }
+
+               public abstract MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state);
+               public abstract FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture);
+               public abstract object ChangeType(object value, Type type, CultureInfo culture);
+               public abstract void ReorderArgumentArray(ref object[] args, object state);
+               public abstract MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers);
+               public abstract PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers);
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/ConstructorInfo.cs b/mcs/class/IKVM.Reflection/ConstructorInfo.cs
new file mode 100644 (file)
index 0000000..69e2b4d
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+
+namespace IKVM.Reflection
+{
+       public abstract class ConstructorInfo : MethodBase
+       {
+               public static readonly string ConstructorName = ".ctor";
+               public static readonly string TypeConstructorName = ".cctor";
+
+               internal abstract MethodInfo GetMethodInfo();
+
+               internal override MethodBase BindTypeParameters(Type type)
+               {
+                       return new ConstructorInfoImpl((MethodInfo)GetMethodInfo().BindTypeParameters(type));
+               }
+
+               public sealed override MemberTypes MemberType
+               {
+                       get { return MemberTypes.Constructor; }
+               }
+
+               public override bool ContainsGenericParameters
+               {
+                       get { return GetMethodInfo().ContainsGenericParameters; }
+               }
+
+               public sealed override ParameterInfo[] GetParameters()
+               {
+                       ParameterInfo[] parameters = GetMethodInfo().GetParameters();
+                       for (int i = 0; i < parameters.Length; i++)
+                       {
+                               parameters[i] = new ParameterInfoWrapper(this, parameters[i]);
+                       }
+                       return parameters;
+               }
+
+               private sealed class ParameterInfoWrapper : ParameterInfo
+               {
+                       private readonly ConstructorInfo ctor;
+                       private readonly ParameterInfo forward;
+
+                       internal ParameterInfoWrapper(ConstructorInfo ctor, ParameterInfo forward)
+                       {
+                               this.ctor = ctor;
+                               this.forward = forward;
+                       }
+
+                       public override string Name
+                       {
+                               get { return forward.Name; }
+                       }
+
+                       public override Type ParameterType
+                       {
+                               get { return forward.ParameterType; }
+                       }
+
+                       public override ParameterAttributes Attributes
+                       {
+                               get { return forward.Attributes; }
+                       }
+
+                       public override int Position
+                       {
+                               get { return forward.Position; }
+                       }
+
+                       public override object RawDefaultValue
+                       {
+                               get { return forward.RawDefaultValue; }
+                       }
+
+                       public override Type[] GetOptionalCustomModifiers()
+                       {
+                               return forward.GetOptionalCustomModifiers();
+                       }
+
+                       public override Type[] GetRequiredCustomModifiers()
+                       {
+                               return forward.GetRequiredCustomModifiers();
+                       }
+
+                       public override MemberInfo Member
+                       {
+                               get { return ctor; }
+                       }
+
+                       public override int MetadataToken
+                       {
+                               get { return forward.MetadataToken; }
+                       }
+
+                       internal override Module Module
+                       {
+                               get { return ctor.Module; }
+                       }
+
+                       internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+                       {
+                               return forward.GetCustomAttributesData(attributeType);
+                       }
+               }
+       }
+
+       sealed class ConstructorInfoImpl : ConstructorInfo
+       {
+               private readonly MethodInfo method;
+
+               internal ConstructorInfoImpl(MethodInfo method)
+               {
+                       this.method = method;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       ConstructorInfoImpl other = obj as ConstructorInfoImpl;
+                       return other != null && other.method.Equals(method);
+               }
+
+               public override int GetHashCode()
+               {
+                       return method.GetHashCode();
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       return method.GetMethodBody();
+               }
+
+               public override CallingConventions CallingConvention
+               {
+                       get { return method.CallingConvention; }
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { return method.Attributes; }
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       return method.GetMethodImplementationFlags();
+               }
+
+               internal override int ParameterCount
+               {
+                       get { return method.ParameterCount; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return method.DeclaringType; }
+               }
+
+               public override string Name
+               {
+                       get { return method.Name; }
+               }
+
+               public override string ToString()
+               {
+                       return method.ToString();
+               }
+
+               public override Module Module
+               {
+                       get { return method.Module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return method.MetadataToken; }
+               }
+
+               internal override MethodInfo GetMethodInfo()
+               {
+                       return method;
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return method.GetCustomAttributesData(attributeType);
+               }
+
+               internal override MethodInfo GetMethodOnTypeDefinition()
+               {
+                       return method.GetMethodOnTypeDefinition();
+               }
+
+               internal override MethodSignature MethodSignature
+               {
+                       get { return method.MethodSignature; }
+               }
+
+               internal override int ImportTo(Emit.ModuleBuilder module)
+               {
+                       return method.ImportTo(module);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/CustomAttributeData.cs b/mcs/class/IKVM.Reflection/CustomAttributeData.cs
new file mode 100644 (file)
index 0000000..5af366b
--- /dev/null
@@ -0,0 +1,612 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+       public sealed class CustomAttributeData
+       {
+               internal static readonly IList<CustomAttributeData> EmptyList = new List<CustomAttributeData>(0).AsReadOnly();
+               private Module module;
+               private int index;
+               private ConstructorInfo lazyConstructor;
+               private IList<CustomAttributeTypedArgument> lazyConstructorArguments;
+               private IList<CustomAttributeNamedArgument> lazyNamedArguments;
+
+               internal CustomAttributeData(Module module, int index)
+               {
+                       this.module = module;
+                       this.index = index;
+               }
+
+               internal CustomAttributeData(ConstructorInfo constructor, object[] args, List<CustomAttributeNamedArgument> namedArguments)
+               {
+                       this.lazyConstructor = constructor;
+                       MethodSignature sig = constructor.MethodSignature;
+                       List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
+                       for (int i = 0; i < args.Length; i++)
+                       {
+                               list.Add(new CustomAttributeTypedArgument(sig.GetParameterType(i), args[i]));
+                       }
+                       lazyConstructorArguments = list.AsReadOnly();
+                       if (namedArguments == null)
+                       {
+                               this.lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
+                       }
+                       else
+                       {
+                               this.lazyNamedArguments = namedArguments.AsReadOnly();
+                       }
+               }
+
+               internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, ByteReader br)
+               {
+                       this.lazyConstructor = constructor;
+                       if (br.Length == 0)
+                       {
+                               // it's legal to have an empty blob
+                               lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
+                               lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
+                       }
+                       else
+                       {
+                               if (br.ReadUInt16() != 1)
+                               {
+                                       throw new BadImageFormatException();
+                               }
+                               lazyConstructorArguments = ReadConstructorArguments(asm, br, constructor);
+                               lazyNamedArguments = ReadNamedArguments(asm, br, br.ReadUInt16(), constructor.DeclaringType);
+                       }
+               }
+
+               public override string ToString()
+               {
+                       StringBuilder sb = new StringBuilder();
+                       sb.Append('[');
+                       sb.Append(Constructor.DeclaringType.FullName);
+                       sb.Append('(');
+                       string sep = "";
+                       foreach (CustomAttributeTypedArgument arg in ConstructorArguments)
+                       {
+                               sb.Append(sep);
+                               sep = ", ";
+                               AppendValue(sb, arg);
+                       }
+                       foreach (CustomAttributeNamedArgument named in NamedArguments)
+                       {
+                               sb.Append(sep);
+                               sep = ", ";
+                               sb.Append(named.MemberInfo.Name);
+                               sb.Append(" = ");
+                               AppendValue(sb, named.TypedValue);
+                       }
+                       sb.Append(')');
+                       sb.Append(']');
+                       return sb.ToString();
+               }
+
+               private static void AppendValue(StringBuilder sb, CustomAttributeTypedArgument arg)
+               {
+                       if (arg.ArgumentType == arg.ArgumentType.Module.universe.System_String)
+                       {
+                               sb.Append('"').Append(arg.Value).Append('"');
+                       }
+                       else
+                       {
+                               if (arg.ArgumentType.IsEnum)
+                               {
+                                       sb.Append('(');
+                                       sb.Append(arg.ArgumentType.FullName);
+                                       sb.Append(')');
+                               }
+                               sb.Append(arg.Value);
+                       }
+               }
+
+               internal static void ReadDeclarativeSecurity(Assembly asm, List<CustomAttributeData> list, int action, ByteReader br)
+               {
+                       Universe u = asm.universe;
+                       if (br.PeekByte() == '.')
+                       {
+                               br.ReadByte();
+                               int count = br.ReadCompressedInt();
+                               for (int j = 0; j < count; j++)
+                               {
+                                       Type type = ReadType(asm, br);
+                                       ConstructorInfo constructor;
+                                       if (type == u.System_Security_Permissions_HostProtectionAttribute && action == (int)System.Security.Permissions.SecurityAction.LinkDemand)
+                                       {
+                                               constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
+                                       }
+                                       else
+                                       {
+                                               constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { u.System_Security_Permissions_SecurityAction }, null);
+                                       }
+                                       // LAMESPEC there is an additional length here (probably of the named argument list)
+                                       ByteReader slice = br.Slice(br.ReadCompressedInt());
+                                       // LAMESPEC the count of named arguments is a compressed integer (instead of UInt16 as NumNamed in custom attributes)
+                                       list.Add(new CustomAttributeData(constructor, action, ReadNamedArguments(asm, slice, slice.ReadCompressedInt(), type)));
+                               }
+                       }
+                       else
+                       {
+                               // .NET 1.x format (xml)
+                               char[] buf = new char[br.Length / 2];
+                               for (int i = 0; i < buf.Length; i++)
+                               {
+                                       buf[i] = br.ReadChar();
+                               }
+                               string xml = new String(buf);
+                               ConstructorInfo constructor = u.System_Security_Permissions_PermissionSetAttribute.GetConstructor(new Type[] { u.System_Security_Permissions_SecurityAction });
+                               List<CustomAttributeNamedArgument> args = new List<CustomAttributeNamedArgument>();
+                               args.Add(new CustomAttributeNamedArgument(u.System_Security_Permissions_PermissionSetAttribute.GetProperty("XML"),
+                                       new CustomAttributeTypedArgument(u.System_String, xml)));
+                               list.Add(new CustomAttributeData(constructor, action, args));
+                       }
+               }
+
+               private CustomAttributeData(ConstructorInfo constructor, int securityAction, IList<CustomAttributeNamedArgument> namedArguments)
+               {
+                       Universe u = constructor.Module.universe;
+                       this.lazyConstructor = constructor;
+                       List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
+                       list.Add(new CustomAttributeTypedArgument(u.System_Security_Permissions_SecurityAction, securityAction));
+                       this.lazyConstructorArguments =  list.AsReadOnly();
+                       this.lazyNamedArguments = namedArguments;
+               }
+
+               private static Type ReadFieldOrPropType(Assembly asm, ByteReader br)
+               {
+                       Universe u = asm.universe;
+                       switch (br.ReadByte())
+                       {
+                               case Signature.ELEMENT_TYPE_BOOLEAN:
+                                       return u.System_Boolean;
+                               case Signature.ELEMENT_TYPE_CHAR:
+                                       return u.System_Char;
+                               case Signature.ELEMENT_TYPE_I1:
+                                       return u.System_SByte;
+                               case Signature.ELEMENT_TYPE_U1:
+                                       return u.System_Byte;
+                               case Signature.ELEMENT_TYPE_I2:
+                                       return u.System_Int16;
+                               case Signature.ELEMENT_TYPE_U2:
+                                       return u.System_UInt16;
+                               case Signature.ELEMENT_TYPE_I4:
+                                       return u.System_Int32;
+                               case Signature.ELEMENT_TYPE_U4:
+                                       return u.System_UInt32;
+                               case Signature.ELEMENT_TYPE_I8:
+                                       return u.System_Int64;
+                               case Signature.ELEMENT_TYPE_U8:
+                                       return u.System_UInt64;
+                               case Signature.ELEMENT_TYPE_R4:
+                                       return u.System_Single;
+                               case Signature.ELEMENT_TYPE_R8:
+                                       return u.System_Double;
+                               case Signature.ELEMENT_TYPE_STRING:
+                                       return u.System_String;
+                               case Signature.ELEMENT_TYPE_SZARRAY:
+                                       return ReadFieldOrPropType(asm, br).MakeArrayType();
+                               case 0x55:
+                                       return ReadType(asm, br);
+                               case 0x50:
+                                       return u.System_Type;
+                               case 0x51:
+                                       return u.System_Object;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+               }
+
+               private static CustomAttributeTypedArgument ReadFixedArg(Assembly asm, ByteReader br, Type type)
+               {
+                       Universe u = asm.universe;
+                       if (type == u.System_String)
+                       {
+                               return new CustomAttributeTypedArgument(type, br.ReadString());
+                       }
+                       else if (type == u.System_Type)
+                       {
+                               return new CustomAttributeTypedArgument(type, ReadType(asm, br));
+                       }
+                       else if (type == u.System_Object)
+                       {
+                               return ReadFixedArg(asm, br, ReadFieldOrPropType(asm, br));
+                       }
+                       else if (type.IsArray)
+                       {
+                               int length = br.ReadInt32();
+                               if (length == -1)
+                               {
+                                       return new CustomAttributeTypedArgument(type, null);
+                               }
+                               Type elementType = type.GetElementType();
+                               CustomAttributeTypedArgument[] array = new CustomAttributeTypedArgument[length];
+                               for (int i = 0; i < length; i++)
+                               {
+                                       array[i] = ReadFixedArg(asm, br, elementType);
+                               }
+                               return new CustomAttributeTypedArgument(type, array);
+                       }
+                       else if (type.IsEnum)
+                       {
+                               return new CustomAttributeTypedArgument(type, ReadFixedArg(asm, br, type.GetEnumUnderlyingTypeImpl()).Value);
+                       }
+                       else
+                       {
+                               switch (Type.GetTypeCode(type))
+                               {
+                                       case TypeCode.Boolean:
+                                               return new CustomAttributeTypedArgument(type, br.ReadByte() != 0);
+                                       case TypeCode.Char:
+                                               return new CustomAttributeTypedArgument(type, br.ReadChar());
+                                       case TypeCode.Single:
+                                               return new CustomAttributeTypedArgument(type, br.ReadSingle());
+                                       case TypeCode.Double:
+                                               return new CustomAttributeTypedArgument(type, br.ReadDouble());
+                                       case TypeCode.SByte:
+                                               return new CustomAttributeTypedArgument(type, br.ReadSByte());
+                                       case TypeCode.Int16:
+                                               return new CustomAttributeTypedArgument(type, br.ReadInt16());
+                                       case TypeCode.Int32:
+                                               return new CustomAttributeTypedArgument(type, br.ReadInt32());
+                                       case TypeCode.Int64:
+                                               return new CustomAttributeTypedArgument(type, br.ReadInt64());
+                                       case TypeCode.Byte:
+                                               return new CustomAttributeTypedArgument(type, br.ReadByte());
+                                       case TypeCode.UInt16:
+                                               return new CustomAttributeTypedArgument(type, br.ReadUInt16());
+                                       case TypeCode.UInt32:
+                                               return new CustomAttributeTypedArgument(type, br.ReadUInt32());
+                                       case TypeCode.UInt64:
+                                               return new CustomAttributeTypedArgument(type, br.ReadUInt64());
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                       }
+               }
+
+               private static Type ReadType(Assembly asm, ByteReader br)
+               {
+                       string typeName = br.ReadString();
+                       if (typeName == null)
+                       {
+                               return null;
+                       }
+                       if (typeName.Length > 0 && typeName[typeName.Length - 1] == 0)
+                       {
+                               // there are broken compilers that emit an extra NUL character after the type name
+                               typeName = typeName.Substring(0, typeName.Length - 1);
+                       }
+                       return asm.universe.GetType(asm, typeName, true);
+               }
+
+               private static IList<CustomAttributeTypedArgument> ReadConstructorArguments(Assembly asm, ByteReader br, ConstructorInfo constructor)
+               {
+                       MethodSignature sig = constructor.MethodSignature;
+                       int count = sig.GetParameterCount();
+                       List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>(count);
+                       for (int i = 0; i < count; i++)
+                       {
+                               list.Add(ReadFixedArg(asm, br, sig.GetParameterType(i)));
+                       }
+                       return list.AsReadOnly();
+               }
+
+               private static IList<CustomAttributeNamedArgument> ReadNamedArguments(Assembly asm, ByteReader br, int named, Type type)
+               {
+                       List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>(named);
+                       for (int i = 0; i < named; i++)
+                       {
+                               byte fieldOrProperty = br.ReadByte();
+                               Type fieldOrPropertyType = ReadFieldOrPropType(asm, br);
+                               string name = br.ReadString();
+                               CustomAttributeTypedArgument value = ReadFixedArg(asm, br, fieldOrPropertyType);
+                               MemberInfo member;
+                               switch (fieldOrProperty)
+                               {
+                                       case 0x53:
+                                               member = GetField(type, name);
+                                               break;
+                                       case 0x54:
+                                               member = GetProperty(type, name);
+                                               break;
+                                       default:
+                                               throw new BadImageFormatException();
+                               }
+                               if (member == null)
+                               {
+                                       throw new BadImageFormatException();
+                               }
+                               list.Add(new CustomAttributeNamedArgument(member, value));
+                       }
+                       return list.AsReadOnly();
+               }
+
+               private static FieldInfo GetField(Type type, string name)
+               {
+                       for (; type != null; type = type.BaseType)
+                       {
+                               foreach (FieldInfo field in type.__GetDeclaredFields())
+                               {
+                                       if (field.IsPublic && !field.IsStatic && field.Name == name)
+                                       {
+                                               return field;
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
+               private static PropertyInfo GetProperty(Type type, string name)
+               {
+                       for (; type != null; type = type.BaseType)
+                       {
+                               foreach (PropertyInfo property in type.__GetDeclaredProperties())
+                               {
+                                       if (property.IsPublic && !property.IsStatic && property.Name == name)
+                                       {
+                                               return property;
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
+               public void __ReadTypeName(out string ns, out string name)
+               {
+                       if (lazyConstructor == null)
+                       {
+                               ModuleReader mod = module as ModuleReader;
+                               if (mod != null)
+                               {
+                                       int methodToken = mod.CustomAttribute.records[index].Type;
+                                       if ((methodToken >> 24) == MemberRefTable.Index)
+                                       {
+                                               int methodIndex = (methodToken & 0xFFFFFF) - 1;
+                                               int typeToken = mod.MemberRef.records[methodIndex].Class;
+                                               if ((typeToken >> 24) == TypeRefTable.Index)
+                                               {
+                                                       int typeIndex = (typeToken & 0xFFFFFF) - 1;
+                                                       int typeNameSpace = mod.TypeRef.records[typeIndex].TypeNameSpace;
+                                                       ns = typeNameSpace == 0 ? null : mod.GetString(typeNameSpace);
+                                                       name = mod.GetString(mod.TypeRef.records[typeIndex].TypeName);
+                                                       return;
+                                               }
+                                       }
+                               }
+                       }
+                       ns = Constructor.DeclaringType.Namespace;
+                       name = Constructor.DeclaringType.Name;
+               }
+
+               public ConstructorInfo Constructor
+               {
+                       get
+                       {
+                               if (lazyConstructor == null)
+                               {
+                                       lazyConstructor = (ConstructorInfo)module.ResolveMethod(module.CustomAttribute.records[index].Type);
+                               }
+                               return lazyConstructor;
+                       }
+               }
+
+               public IList<CustomAttributeTypedArgument> ConstructorArguments
+               {
+                       get
+                       {
+                               if (lazyConstructorArguments == null)
+                               {
+                                       LazyParseArguments();
+                               }
+                               return lazyConstructorArguments;
+                       }
+               }
+
+               public IList<CustomAttributeNamedArgument> NamedArguments
+               {
+                       get
+                       {
+                               if (lazyNamedArguments == null)
+                               {
+                                       LazyParseArguments();
+                               }
+                               return lazyNamedArguments;
+                       }
+               }
+
+               private void LazyParseArguments()
+               {
+                       ByteReader br = module.GetBlob(module.CustomAttribute.records[index].Value);
+                       if (br.Length == 0)
+                       {
+                               // it's legal to have an empty blob
+                               lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
+                               lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
+                       }
+                       else
+                       {
+                               if (br.ReadUInt16() != 1)
+                               {
+                                       throw new BadImageFormatException();
+                               }
+                               lazyConstructorArguments = ReadConstructorArguments(module.Assembly, br, Constructor);
+                               lazyNamedArguments = ReadNamedArguments(module.Assembly, br, br.ReadUInt16(), Constructor.DeclaringType);
+                       }
+               }
+
+               public CustomAttributeBuilder __ToBuilder()
+               {
+                       object[] args = new object[ConstructorArguments.Count];
+                       for (int i = 0; i < args.Length; i++)
+                       {
+                               args[i] = ConstructorArguments[i].Value;
+                       }
+                       List<PropertyInfo> namedProperties = new List<PropertyInfo>();
+                       List<object> propertyValues = new List<object>();
+                       List<FieldInfo> namedFields = new List<FieldInfo>();
+                       List<object> fieldValues = new List<object>();
+                       foreach (CustomAttributeNamedArgument named in NamedArguments)
+                       {
+                               if (named.MemberInfo is PropertyInfo)
+                               {
+                                       namedProperties.Add((PropertyInfo)named.MemberInfo);
+                                       propertyValues.Add(named.TypedValue.Value);
+                               }
+                               else
+                               {
+                                       namedFields.Add((FieldInfo)named.MemberInfo);
+                                       fieldValues.Add(named.TypedValue.Value);
+                               }
+                       }
+                       return new CustomAttributeBuilder(Constructor, args, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray());
+               }
+
+               public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo member)
+               {
+                       return member.GetCustomAttributesData(null);
+               }
+
+               public static IList<CustomAttributeData> GetCustomAttributes(Assembly assembly)
+               {
+                       return assembly.GetCustomAttributesData(null);
+               }
+
+               public static IList<CustomAttributeData> GetCustomAttributes(Module module)
+               {
+                       return module.GetCustomAttributesData(null);
+               }
+
+               public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo parameter)
+               {
+                       return parameter.GetCustomAttributesData(null);
+               }
+
+               public static IList<CustomAttributeData> __GetCustomAttributes(Assembly assembly, Type attributeType, bool inherit)
+               {
+                       return assembly.GetCustomAttributesData(attributeType);
+               }
+
+               public static IList<CustomAttributeData> __GetCustomAttributes(Module module, Type attributeType, bool inherit)
+               {
+                       return module.GetCustomAttributesData(attributeType);
+               }
+
+               public static IList<CustomAttributeData> __GetCustomAttributes(ParameterInfo parameter, Type attributeType, bool inherit)
+               {
+                       return parameter.GetCustomAttributesData(attributeType);
+               }
+
+               public static IList<CustomAttributeData> __GetCustomAttributes(MemberInfo member, Type attributeType, bool inherit)
+               {
+                       if (!inherit || !IsInheritableAttribute(attributeType))
+                       {
+                               return member.GetCustomAttributesData(attributeType);
+                       }
+                       List<CustomAttributeData> list = new List<CustomAttributeData>();
+                       for (; ; )
+                       {
+                               list.AddRange(member.GetCustomAttributesData(attributeType));
+                               Type type = member as Type;
+                               if (type != null)
+                               {
+                                       type = type.BaseType;
+                                       if (type == null)
+                                       {
+                                               return list;
+                                       }
+                                       member = type;
+                                       continue;
+                               }
+                               MethodInfo method = member as MethodInfo;
+                               if (method != null)
+                               {
+                                       MemberInfo prev = member;
+                                       method = method.GetBaseDefinition();
+                                       if (method == null || method == prev)
+                                       {
+                                               return list;
+                                       }
+                                       member = method;
+                                       continue;
+                               }
+                               return list;
+                       }
+               }
+
+               public static IList<CustomAttributeData> __GetDeclarativeSecurity(Assembly assembly)
+               {
+                       return assembly.ManifestModule.GetDeclarativeSecurity(0x20000001);
+               }
+
+               public static IList<CustomAttributeData> __GetDeclarativeSecurity(Type type)
+               {
+                       if ((type.Attributes & TypeAttributes.HasSecurity) != 0)
+                       {
+                               return type.Module.GetDeclarativeSecurity(type.MetadataToken);
+                       }
+                       else
+                       {
+                               return EmptyList;
+                       }
+               }
+
+               public static IList<CustomAttributeData> __GetDeclarativeSecurity(MethodBase method)
+               {
+                       if ((method.Attributes & MethodAttributes.HasSecurity) != 0)
+                       {
+                               return method.Module.GetDeclarativeSecurity(method.MetadataToken);
+                       }
+                       else
+                       {
+                               return EmptyList;
+                       }
+               }
+
+               private static bool IsInheritableAttribute(Type attribute)
+               {
+                       Type attributeUsageAttribute = attribute.Module.universe.System_AttributeUsageAttribute;
+                       IList<CustomAttributeData> attr = attribute.GetCustomAttributesData(attributeUsageAttribute);
+                       if (attr.Count != 0)
+                       {
+                               foreach (CustomAttributeNamedArgument named in attr[0].NamedArguments)
+                               {
+                                       if (named.MemberInfo.Name == "Inherited")
+                                       {
+                                               return (bool)named.TypedValue.Value;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/CustomAttributeNamedArgument.cs b/mcs/class/IKVM.Reflection/CustomAttributeNamedArgument.cs
new file mode 100644 (file)
index 0000000..d9a84b7
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       public struct CustomAttributeNamedArgument
+       {
+               private readonly MemberInfo member;
+               private readonly CustomAttributeTypedArgument value;
+
+               internal CustomAttributeNamedArgument(MemberInfo member, CustomAttributeTypedArgument value)
+               {
+                       this.member = member;
+                       this.value = value;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return this == obj as CustomAttributeNamedArgument?;
+               }
+
+               public override int GetHashCode()
+               {
+                       return member.GetHashCode() ^ 53 * value.GetHashCode();
+               }
+
+               public MemberInfo MemberInfo
+               {
+                       get { return member; }
+               }
+
+               public CustomAttributeTypedArgument TypedValue
+               {
+                       get { return value; }
+               }
+
+               public static bool operator ==(CustomAttributeNamedArgument arg1, CustomAttributeNamedArgument arg2)
+               {
+                       return arg1.member.Equals(arg2.member) && arg1.value == arg2.value;
+               }
+
+               public static bool operator !=(CustomAttributeNamedArgument arg1, CustomAttributeNamedArgument arg2)
+               {
+                       return !(arg1 == arg2);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/CustomAttributeTypedArgument.cs b/mcs/class/IKVM.Reflection/CustomAttributeTypedArgument.cs
new file mode 100644 (file)
index 0000000..3403135
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       public struct CustomAttributeTypedArgument
+       {
+               private readonly Type type;
+               private readonly object value;
+
+               internal CustomAttributeTypedArgument(Type type, object value)
+               {
+                       this.type = type;
+                       this.value = value;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return this == obj as CustomAttributeTypedArgument?;
+               }
+
+               public override int GetHashCode()
+               {
+                       return type.GetHashCode() ^ 77 * (value == null ? 0 : value.GetHashCode());
+               }
+
+               public Type ArgumentType
+               {
+                       get { return type; }
+               }
+
+               public Object Value
+               {
+                       get { return value; }
+               }
+
+               public static bool operator ==(CustomAttributeTypedArgument arg1, CustomAttributeTypedArgument arg2)
+               {
+                       return arg1.type.Equals(arg2.type) && (arg1.value == arg2.value || (arg1.value != null && arg1.value.Equals(arg2.value)));
+               }
+
+               public static bool operator !=(CustomAttributeTypedArgument arg1, CustomAttributeTypedArgument arg2)
+               {
+                       return !(arg1 == arg2);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/AssemblyBuilder.cs b/mcs/class/IKVM.Reflection/Emit/AssemblyBuilder.cs
new file mode 100644 (file)
index 0000000..9919fd3
--- /dev/null
@@ -0,0 +1,721 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Configuration.Assemblies;
+using System.IO;
+using System.Diagnostics;
+using System.Globalization;
+using System.Security.Cryptography;
+using System.Security;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class AssemblyBuilder : Assembly
+       {
+               private readonly string name;
+               private ushort majorVersion;
+               private ushort minorVersion;
+               private ushort buildVersion;
+               private ushort revisionVersion;
+               private string culture;
+               private AssemblyNameFlags flags;
+               private AssemblyHashAlgorithm hashAlgorithm;
+               private StrongNameKeyPair keyPair;
+               private byte[] publicKey;
+               internal readonly string dir;
+               private readonly PermissionSet requiredPermissions;
+               private readonly PermissionSet optionalPermissions;
+               private readonly PermissionSet refusedPermissions;
+               private PEFileKinds fileKind = PEFileKinds.Dll;
+               private MethodInfo entryPoint;
+               private VersionInfo versionInfo;
+               private ResourceSection unmanagedResources;
+               private string imageRuntimeVersion;
+               internal int mdStreamVersion = 0x20000;
+               private Module pseudoManifestModule;
+               private readonly List<ResourceFile> resourceFiles = new List<ResourceFile>();
+               private readonly List<ModuleBuilder> modules = new List<ModuleBuilder>();
+               private readonly List<Module> addedModules = new List<Module>();
+               private readonly List<CustomAttributeBuilder> customAttributes = new List<CustomAttributeBuilder>();
+               private readonly List<CustomAttributeBuilder> declarativeSecurity = new List<CustomAttributeBuilder>();
+               private readonly List<Type> typeForwarders = new List<Type>();
+
+               private struct ResourceFile
+               {
+                       internal string Name;
+                       internal string FileName;
+                       internal ResourceAttributes Attributes;
+               }
+
+               internal AssemblyBuilder(Universe universe, AssemblyName name, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
+                       : base(universe)
+               {
+                       this.name = name.Name;
+                       SetVersionHelper(name.Version);
+                       if (name.CultureInfo != null && !string.IsNullOrEmpty(name.CultureInfo.Name))
+                       {
+                               this.culture = name.CultureInfo.Name;
+                       }
+                       this.flags = name.Flags;
+                       this.hashAlgorithm = name.HashAlgorithm;
+                       if (this.hashAlgorithm == AssemblyHashAlgorithm.None)
+                       {
+                               this.hashAlgorithm = AssemblyHashAlgorithm.SHA1;
+                       }
+                       this.keyPair = name.KeyPair;
+                       if (this.keyPair != null)
+                       {
+                               this.publicKey = this.keyPair.PublicKey;
+                       }
+                       else
+                       {
+                               byte[] publicKey = name.GetPublicKey();
+                               if (publicKey != null && publicKey.Length != 0)
+                               {
+                                       this.publicKey = (byte[])publicKey.Clone();
+                               }
+                       }
+                       this.dir = dir ?? ".";
+                       this.requiredPermissions = requiredPermissions;
+                       this.optionalPermissions = optionalPermissions;
+                       this.refusedPermissions = refusedPermissions;
+                       if (universe.HasMscorlib && universe.Mscorlib.ImageRuntimeVersion != null)
+                       {
+                               this.imageRuntimeVersion = universe.Mscorlib.ImageRuntimeVersion;
+                       }
+                       else
+                       {
+                               this.imageRuntimeVersion = typeof(object).Assembly.ImageRuntimeVersion;
+                       }
+               }
+
+               private void SetVersionHelper(Version version)
+               {
+                       if (version == null)
+                       {
+                               majorVersion = 0;
+                               minorVersion = 0;
+                               buildVersion = 0;
+                               revisionVersion = 0;
+                       }
+                       else
+                       {
+                               majorVersion = (ushort)version.Major;
+                               minorVersion = (ushort)version.Minor;
+                               buildVersion = version.Build == -1 ? (ushort)0 : (ushort)version.Build;
+                               revisionVersion = version.Revision == -1 ? (ushort)0 : (ushort)version.Revision;
+                       }
+               }
+
+               public void __SetAssemblyVersion(Version version)
+               {
+                       AssemblyName oldName = GetName();
+                       SetVersionHelper(version);
+                       universe.RenameAssembly(this, oldName);
+               }
+
+               public void __SetAssemblyCulture(string cultureName)
+               {
+                       AssemblyName oldName = GetName();
+                       this.culture = cultureName;
+                       universe.RenameAssembly(this, oldName);
+               }
+
+               public void __SetAssemblyKeyPair(StrongNameKeyPair keyPair)
+               {
+                       AssemblyName oldName = GetName();
+                       this.keyPair = keyPair;
+                       if (keyPair != null)
+                       {
+                               this.publicKey = keyPair.PublicKey;
+                       }
+                       universe.RenameAssembly(this, oldName);
+               }
+
+               // this is used in combination with delay signing
+               public void __SetAssemblyPublicKey(byte[] publicKey)
+               {
+                       AssemblyName oldName = GetName();
+                       this.publicKey = publicKey == null ? null : (byte[])publicKey.Clone();
+                       universe.RenameAssembly(this, oldName);
+               }
+
+               public void __SetAssemblyAlgorithmId(AssemblyHashAlgorithm hashAlgorithm)
+               {
+                       this.hashAlgorithm = hashAlgorithm;
+               }
+
+               public void __SetAssemblyFlags(AssemblyNameFlags flags)
+               {
+                       this.flags = flags;
+               }
+
+               public override AssemblyName GetName()
+               {
+                       AssemblyName n = new AssemblyName();
+                       n.Name = name;
+                       n.Version = new Version(majorVersion, minorVersion, buildVersion, revisionVersion);
+                       n.Culture = culture;
+                       n.HashAlgorithm = hashAlgorithm;
+                       n.Flags = flags;
+                       n.SetPublicKey(publicKey != null ? (byte[])publicKey.Clone() : Empty<byte>.Array);
+                       n.KeyPair = keyPair;
+                       return n;
+               }
+
+               public override string FullName
+               {
+                       get { return GetName().FullName; }
+               }
+
+               public override string Location
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public ModuleBuilder DefineDynamicModule(string name, string fileName)
+               {
+                       return DefineDynamicModule(name, fileName, false);
+               }
+
+               public ModuleBuilder DefineDynamicModule(string name, string fileName, bool emitSymbolInfo)
+               {
+                       ModuleBuilder module = new ModuleBuilder(this, name, fileName, emitSymbolInfo);
+                       modules.Add(module);
+                       return module;
+               }
+
+               public ModuleBuilder GetDynamicModule(string name)
+               {
+                       foreach (ModuleBuilder module in modules)
+                       {
+                               if (module.Name == name)
+                               {
+                                       return module;
+                               }
+                       }
+                       return null;
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       customAttributes.Add(customBuilder);
+               }
+
+               public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+               {
+                       declarativeSecurity.Add(customBuilder);
+               }
+
+               public void __AddTypeForwarder(Type type)
+               {
+                       typeForwarders.Add(type);
+               }
+
+               public void SetEntryPoint(MethodInfo entryMethod)
+               {
+                       SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication);
+               }
+
+               public void SetEntryPoint(MethodInfo entryMethod, PEFileKinds fileKind)
+               {
+                       this.entryPoint = entryMethod;
+                       this.fileKind = fileKind;
+               }
+
+               public void Save(string assemblyFileName)
+               {
+                       Save(assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
+               }
+
+               public void Save(string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+               {
+                       ModuleBuilder manifestModule = null;
+
+                       foreach (ModuleBuilder moduleBuilder in modules)
+                       {
+                               moduleBuilder.PopulatePropertyAndEventTables();
+
+                               if (manifestModule == null
+                                       && string.Compare(moduleBuilder.fileName, assemblyFileName, StringComparison.OrdinalIgnoreCase) == 0)
+                               {
+                                       manifestModule = moduleBuilder;
+                               }
+                       }
+
+                       if (manifestModule == null)
+                       {
+                               manifestModule = DefineDynamicModule("RefEmit_OnDiskManifestModule", assemblyFileName, false);
+                       }
+
+                       AssemblyTable.Record assemblyRecord = new AssemblyTable.Record();
+                       assemblyRecord.HashAlgId = (int)hashAlgorithm;
+                       assemblyRecord.Name = manifestModule.Strings.Add(name);
+                       assemblyRecord.MajorVersion = majorVersion;
+                       assemblyRecord.MinorVersion = minorVersion;
+                       assemblyRecord.BuildNumber = buildVersion;
+                       assemblyRecord.RevisionNumber = revisionVersion;
+                       if (publicKey != null)
+                       {
+                               assemblyRecord.PublicKey = manifestModule.Blobs.Add(ByteBuffer.Wrap(publicKey));
+                               assemblyRecord.Flags = (int)(flags | AssemblyNameFlags.PublicKey);
+                       }
+                       else
+                       {
+                               assemblyRecord.Flags = (int)(flags & ~AssemblyNameFlags.PublicKey);
+                       }
+                       if (culture != null)
+                       {
+                               assemblyRecord.Culture = manifestModule.Strings.Add(culture);
+                       }
+                       int token = 0x20000000 + manifestModule.AssemblyTable.AddRecord(assemblyRecord);
+
+#pragma warning disable 618
+                       // this values are obsolete, but we already know that so we disable the warning
+                       System.Security.Permissions.SecurityAction requestMinimum = System.Security.Permissions.SecurityAction.RequestMinimum;
+                       System.Security.Permissions.SecurityAction requestOptional = System.Security.Permissions.SecurityAction.RequestOptional;
+                       System.Security.Permissions.SecurityAction requestRefuse = System.Security.Permissions.SecurityAction.RequestRefuse;
+#pragma warning restore 618
+                       if (requiredPermissions != null)
+                       {
+                               manifestModule.AddDeclarativeSecurity(token, requestMinimum, requiredPermissions);
+                       }
+                       if (optionalPermissions != null)
+                       {
+                               manifestModule.AddDeclarativeSecurity(token, requestOptional, optionalPermissions);
+                       }
+                       if (refusedPermissions != null)
+                       {
+                               manifestModule.AddDeclarativeSecurity(token, requestRefuse, refusedPermissions);
+                       }
+
+                       if (versionInfo != null)
+                       {
+                               versionInfo.SetName(GetName());
+                               versionInfo.SetFileName(assemblyFileName);
+                               foreach (CustomAttributeBuilder cab in customAttributes)
+                               {
+                                       // .NET doesn't support copying blob custom attributes into the version info
+                                       if (!cab.HasBlob)
+                                       {
+                                               versionInfo.SetAttribute(cab);
+                                       }
+                               }
+                               ByteBuffer versionInfoData = new ByteBuffer(512);
+                               versionInfo.Write(versionInfoData);
+                               if (unmanagedResources == null)
+                               {
+                                       unmanagedResources = new ResourceSection();
+                               }
+                               unmanagedResources.AddVersionInfo(versionInfoData);
+                       }
+
+                       foreach (CustomAttributeBuilder cab in customAttributes)
+                       {
+                               // we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET)
+                               manifestModule.SetCustomAttribute(0x20000001, cab);
+                       }
+
+                       manifestModule.AddDeclarativeSecurity(0x20000001, declarativeSecurity);
+
+                       foreach (Type type in typeForwarders)
+                       {
+                               manifestModule.AddTypeForwarder(type);
+                       }
+
+                       foreach (ResourceFile resfile in resourceFiles)
+                       {
+                               int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
+                               ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
+                               rec.Offset = 0;
+                               rec.Flags = (int)resfile.Attributes;
+                               rec.Name = manifestModule.Strings.Add(resfile.Name);
+                               rec.Implementation = fileToken;
+                               manifestModule.ManifestResource.AddRecord(rec);
+                       }
+
+                       int entryPointToken = 0;
+
+                       foreach (ModuleBuilder moduleBuilder in modules)
+                       {
+                               moduleBuilder.FillAssemblyRefTable();
+                               if (moduleBuilder != manifestModule)
+                               {
+                                       int fileToken;
+                                       if (entryPoint != null && entryPoint.Module == moduleBuilder)
+                                       {
+                                               ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, entryPoint.MetadataToken);
+                                               entryPointToken = fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
+                                       }
+                                       else
+                                       {
+                                               ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, 0);
+                                               fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
+                                       }
+                                       moduleBuilder.ExportTypes(fileToken, manifestModule);
+                               }
+                       }
+
+                       foreach (Module module in addedModules)
+                       {
+                               int fileToken = AddFile(manifestModule, module.FullyQualifiedName, 0 /*ContainsMetaData*/);
+                               module.ExportTypes(fileToken, manifestModule);
+                       }
+
+                       if (entryPointToken == 0 && entryPoint != null)
+                       {
+                               entryPointToken = entryPoint.MetadataToken;
+                       }
+
+                       // finally, write the manifest module
+                       ModuleWriter.WriteModule(keyPair, publicKey, manifestModule, fileKind, portableExecutableKind, imageFileMachine, unmanagedResources ?? manifestModule.unmanagedResources, entryPointToken);
+               }
+
+               private int AddFile(ModuleBuilder manifestModule, string fileName, int flags)
+               {
+                       SHA1Managed hash = new SHA1Managed();
+                       string fullPath = fileName;
+                       if (dir != null)
+                       {
+                               fullPath = Path.Combine(dir, fileName);
+                       }
+                       using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
+                       {
+                               using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
+                               {
+                                       byte[] buf = new byte[8192];
+                                       ModuleWriter.HashChunk(fs, cs, buf, (int)fs.Length);
+                               }
+                       }
+                       FileTable.Record file = new FileTable.Record();
+                       file.Flags = flags;
+                       file.Name = manifestModule.Strings.Add(Path.GetFileName(fileName));
+                       file.HashValue = manifestModule.Blobs.Add(ByteBuffer.Wrap(hash.Hash));
+                       return 0x26000000 + manifestModule.File.AddRecord(file);
+               }
+
+               public void AddResourceFile(string name, string fileName)
+               {
+                       AddResourceFile(name, fileName, ResourceAttributes.Public);
+               }
+
+               public void AddResourceFile(string name, string fileName, ResourceAttributes attribs)
+               {
+                       ResourceFile resfile = new ResourceFile();
+                       resfile.Name = name;
+                       resfile.FileName = fileName;
+                       resfile.Attributes = attribs;
+                       resourceFiles.Add(resfile);
+               }
+
+               public void DefineVersionInfoResource()
+               {
+                       versionInfo = new VersionInfo();
+               }
+
+               public void DefineVersionInfoResource(string product, string productVersion, string company, string copyright, string trademark)
+               {
+                       versionInfo = new VersionInfo();
+                       versionInfo.product = product;
+                       versionInfo.informationalVersion = productVersion;
+                       versionInfo.company = company;
+                       versionInfo.copyright = copyright;
+                       versionInfo.trademark = trademark;
+               }
+
+               public void __DefineIconResource(byte[] iconFile)
+               {
+                       unmanagedResources = new ResourceSection();
+                       unmanagedResources.AddIcon(iconFile);
+               }
+
+               public void __DefineUnmanagedResource(byte[] resource)
+               {
+                       // The standard .NET DefineUnmanagedResource(byte[]) is useless, because it embeds "resource" (as-is) as the .rsrc section,
+                       // but it doesn't set the PE file Resource Directory entry to point to it. That's why we have a renamed version, which behaves
+                       // like DefineUnmanagedResource(string).
+                       unmanagedResources = new ResourceSection();
+                       unmanagedResources.ExtractResources(resource);
+               }
+
+               public void DefineUnmanagedResource(string resourceFileName)
+               {
+                       // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
+                       // also setting the Resource Directory entry.
+                       __DefineUnmanagedResource(File.ReadAllBytes(resourceFileName));
+               }
+
+               public override Type[] GetTypes()
+               {
+                       List<Type> list = new List<Type>();
+                       foreach (ModuleBuilder module in modules)
+                       {
+                               module.GetTypesImpl(list);
+                       }
+                       foreach (Module module in addedModules)
+                       {
+                               module.GetTypesImpl(list);
+                       }
+                       return list.ToArray();
+               }
+
+               internal override Type GetTypeImpl(string typeName)
+               {
+                       foreach (ModuleBuilder mb in modules)
+                       {
+                               Type type = mb.GetTypeImpl(typeName);
+                               if (type != null)
+                               {
+                                       return type;
+                               }
+                       }
+                       foreach (Module module in addedModules)
+                       {
+                               Type type = module.GetTypeImpl(typeName);
+                               if (type != null)
+                               {
+                                       return type;
+                               }
+                       }
+                       return null;
+               }
+
+               public override string ImageRuntimeVersion
+               {
+                       get { return imageRuntimeVersion; }
+               }
+
+               public void __SetImageRuntimeVersion(string imageRuntimeVersion, int mdStreamVersion)
+               {
+                       this.imageRuntimeVersion = imageRuntimeVersion;
+                       this.mdStreamVersion = mdStreamVersion;
+               }
+
+               public override Module ManifestModule
+               {
+                       get
+                       {
+                               if (pseudoManifestModule == null)
+                               {
+                                       pseudoManifestModule = new ManifestModule(this);
+                               }
+                               return pseudoManifestModule;
+                       }
+               }
+
+               public override MethodInfo EntryPoint
+               {
+                       get { return entryPoint; }
+               }
+
+               public override AssemblyName[] GetReferencedAssemblies()
+               {
+                       return Empty<AssemblyName>.Array;
+               }
+
+               public override Module[] GetLoadedModules(bool getResourceModules)
+               {
+                       return GetModules(getResourceModules);
+               }
+
+               public override Module[] GetModules(bool getResourceModules)
+               {
+                       List<Module> list = new List<Module>();
+                       foreach (ModuleBuilder module in modules)
+                       {
+                               if (getResourceModules || !module.IsResource())
+                               {
+                                       list.Add(module);
+                               }
+                       }
+                       foreach (Module module in addedModules)
+                       {
+                               if (getResourceModules || !module.IsResource())
+                               {
+                                       list.Add(module);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public override Module GetModule(string name)
+               {
+                       foreach (ModuleBuilder module in modules)
+                       {
+                               if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
+                               {
+                                       return module;
+                               }
+                       }
+                       foreach (Module module in addedModules)
+                       {
+                               if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
+                               {
+                                       return module;
+                               }
+                       }
+                       return null;
+               }
+
+               public Module __AddModule(RawModule module)
+               {
+                       Module mod = module.ToModule(this);
+                       addedModules.Add(mod);
+                       return mod;
+               }
+
+               public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override string[] GetManifestResourceNames()
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override Stream GetManifestResourceStream(string resourceName)
+               {
+                       throw new NotSupportedException();
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       List<CustomAttributeData> list = new List<CustomAttributeData>();
+                       foreach (CustomAttributeBuilder cab in customAttributes)
+                       {
+                               if (attributeType == null || attributeType.IsAssignableFrom(cab.Constructor.DeclaringType))
+                               {
+                                       list.Add(cab.ToData(this));
+                               }
+                       }
+                       return list;
+               }
+       }
+
+       sealed class ManifestModule : Module
+       {
+               private readonly AssemblyBuilder assembly;
+               private readonly Guid guid = Guid.NewGuid();
+
+               internal ManifestModule(AssemblyBuilder assembly)
+                       : base(assembly.universe)
+               {
+                       this.assembly = assembly;
+               }
+
+               public override int MDStreamVersion
+               {
+                       get { return assembly.mdStreamVersion; }
+               }
+
+               public override Assembly Assembly
+               {
+                       get { return assembly; }
+               }
+
+               internal override Type GetTypeImpl(string typeName)
+               {
+                       return null;
+               }
+
+               internal override void  GetTypesImpl(List<Type> list)
+               {
+               }
+
+               public override string FullyQualifiedName
+               {
+                       get { return Path.Combine(assembly.dir, "RefEmit_InMemoryManifestModule"); }
+               }
+
+               public override string Name
+               {
+                       get { return "<In Memory Module>"; }
+               }
+
+               public override Guid ModuleVersionId
+               {
+                       get { return guid; }
+               }
+
+               public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new ArgumentException();
+               }
+
+               public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new ArgumentException();
+               }
+
+               public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new ArgumentException();
+               }
+
+               public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new ArgumentException();
+               }
+
+               public override string ResolveString(int metadataToken)
+               {
+                       throw new ArgumentException();
+               }
+
+               public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+               {
+                       throw new ArgumentException();
+               }
+
+               public override string ScopeName
+               {
+                       get { return "RefEmit_InMemoryManifestModule"; }
+               }
+
+               public override AssemblyName[] __GetReferencedAssemblies()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal override Type GetModuleType()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+               {
+                       throw new InvalidOperationException();
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/ConstructorBuilder.cs b/mcs/class/IKVM.Reflection/Emit/ConstructorBuilder.cs
new file mode 100644 (file)
index 0000000..9ffc918
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class ConstructorBuilder : ConstructorInfo
+       {
+               private readonly MethodBuilder methodBuilder;
+
+               internal ConstructorBuilder(MethodBuilder mb)
+               {
+                       this.methodBuilder = mb;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       ConstructorBuilder other = obj as ConstructorBuilder;
+                       return other != null && other.methodBuilder.Equals(methodBuilder);
+               }
+
+               public override int GetHashCode()
+               {
+                       return methodBuilder.GetHashCode();
+               }
+
+               public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
+               {
+                       return methodBuilder.DefineParameter(position, attributes, strParamName);
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       methodBuilder.SetCustomAttribute(customBuilder);
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con,     byte[] binaryAttribute)
+               {
+                       methodBuilder.SetCustomAttribute(con, binaryAttribute);
+               }
+
+               public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+               {
+                       methodBuilder.__AddDeclarativeSecurity(customBuilder);
+               }
+
+               public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+               {
+                       methodBuilder.AddDeclarativeSecurity(securityAction, permissionSet);
+               }
+
+               public void SetImplementationFlags(MethodImplAttributes attributes)
+               {
+                       methodBuilder.SetImplementationFlags(attributes);
+               }
+
+               public ILGenerator GetILGenerator()
+               {
+                       return methodBuilder.GetILGenerator();
+               }
+
+               public ILGenerator GetILGenerator(int streamSize)
+               {
+                       return methodBuilder.GetILGenerator(streamSize);
+               }
+
+               public override CallingConventions CallingConvention
+               {
+                       get { return methodBuilder.CallingConvention; }
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { return methodBuilder.Attributes; }
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       return methodBuilder.GetMethodImplementationFlags();
+               }
+
+               public Type ReturnType
+               {
+                       get { return methodBuilder.ReturnType; }
+               }
+
+               internal override int ParameterCount
+               {
+                       get { return methodBuilder.ParameterCount; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return methodBuilder.DeclaringType; }
+               }
+
+               public override string Name
+               {
+                       get { return methodBuilder.Name; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return methodBuilder.MetadataToken; }
+               }
+
+               public override Module Module
+               {
+                       get { return methodBuilder.Module; }
+               }
+
+               public Module GetModule()
+               {
+                       return methodBuilder.GetModule();
+               }
+
+               public MethodToken GetToken()
+               {
+                       return methodBuilder.GetToken();
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       return methodBuilder.GetMethodBody();
+               }
+
+               public bool InitLocals
+               {
+                       get { return methodBuilder.InitLocals; }
+                       set { methodBuilder.InitLocals = value; }
+               }
+
+               internal override MethodInfo GetMethodInfo()
+               {
+                       return methodBuilder;
+               }
+
+               internal override MethodInfo GetMethodOnTypeDefinition()
+               {
+                       return methodBuilder;
+               }
+
+               internal override MethodSignature MethodSignature
+               {
+                       get { return methodBuilder.MethodSignature; }
+               }
+
+               internal override int ImportTo(ModuleBuilder module)
+               {
+                       return module.ImportMember(methodBuilder);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/CustomAttributeBuilder.cs b/mcs/class/IKVM.Reflection/Emit/CustomAttributeBuilder.cs
new file mode 100644 (file)
index 0000000..e4fcff2
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class CustomAttributeBuilder
+       {
+               private readonly ConstructorInfo con;
+               private readonly byte[] blob;
+               private readonly object[] constructorArgs;
+               private readonly PropertyInfo[] namedProperties;
+               private readonly object[] propertyValues;
+               private readonly FieldInfo[] namedFields;
+               private readonly object[] fieldValues;
+
+               internal CustomAttributeBuilder(ConstructorInfo con, byte[] blob)
+               {
+                       this.con = con;
+                       this.blob = blob;
+               }
+
+               public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs)
+                       : this(con, constructorArgs, null, null, null,null)
+               {
+               }
+
+               public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues)
+                       : this(con, constructorArgs, null, null, namedFields, fieldValues)
+               {
+               }
+
+               public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues)
+                       : this(con, constructorArgs, namedProperties, propertyValues, null, null)
+               {
+               }
+
+               public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues)
+               {
+                       this.con = con;
+                       this.constructorArgs = constructorArgs;
+                       this.namedProperties = namedProperties;
+                       this.propertyValues = propertyValues;
+                       this.namedFields = namedFields;
+                       this.fieldValues = fieldValues;
+               }
+
+               private sealed class BlobWriter
+               {
+                       private readonly ModuleBuilder moduleBuilder;
+                       private readonly CustomAttributeBuilder cab;
+                       private readonly ByteBuffer bb;
+
+                       internal BlobWriter(ModuleBuilder moduleBuilder, CustomAttributeBuilder cab, ByteBuffer bb)
+                       {
+                               this.moduleBuilder = moduleBuilder;
+                               this.cab = cab;
+                               this.bb = bb;
+                       }
+
+                       internal void WriteCustomAttributeBlob()
+                       {
+                               // prolog
+                               WriteUInt16(1);
+                               ParameterInfo[] pi = cab.con.GetParameters();
+                               for (int i = 0; i < pi.Length; i++)
+                               {
+                                       WriteFixedArg(pi[i].ParameterType, cab.constructorArgs[i]);
+                               }
+                               WriteNamedArguments(false);
+                       }
+
+                       internal void WriteNamedArguments(bool forDeclSecurity)
+                       {
+                               // NumNamed
+                               int named = 0;
+                               if (cab.namedFields != null)
+                               {
+                                       named += cab.namedFields.Length;
+                               }
+                               if (cab.namedProperties != null)
+                               {
+                                       named += cab.namedProperties.Length;
+                               }
+                               if (forDeclSecurity)
+                               {
+                                       WritePackedLen(named);
+                               }
+                               else
+                               {
+                                       WriteUInt16((ushort)named);
+                               }
+                               if (cab.namedFields != null)
+                               {
+                                       for (int i = 0; i < cab.namedFields.Length; i++)
+                                       {
+                                               WriteNamedArg(0x53, cab.namedFields[i].FieldType, cab.namedFields[i].Name, cab.fieldValues[i]);
+                                       }
+                               }
+                               if (cab.namedProperties != null)
+                               {
+                                       for (int i = 0; i < cab.namedProperties.Length; i++)
+                                       {
+                                               WriteNamedArg(0x54, cab.namedProperties[i].PropertyType, cab.namedProperties[i].Name, cab.propertyValues[i]);
+                                       }
+                               }
+                       }
+
+                       private void WriteNamedArg(byte fieldOrProperty, Type type, string name, object value)
+                       {
+                               WriteByte(fieldOrProperty);
+                               WriteFieldOrPropType(type);
+                               WriteString(name);
+                               WriteFixedArg(type, value);
+                       }
+
+                       private void WriteByte(byte value)
+                       {
+                               bb.Write(value);
+                       }
+
+                       private void WriteUInt16(ushort value)
+                       {
+                               bb.Write(value);
+                       }
+
+                       private void WriteInt32(int value)
+                       {
+                               bb.Write(value);
+                       }
+
+                       private void WriteFixedArg(Type type, object value)
+                       {
+                               Universe u = moduleBuilder.universe;
+                               if (type == u.System_String)
+                               {
+                                       WriteString((string)value);
+                               }
+                               else if (type == u.System_Type)
+                               {
+                                       WriteTypeName((Type)value);
+                               }
+                               else if (type == u.System_Object)
+                               {
+                                       if (value == null)
+                                       {
+                                               type = u.System_String;
+                                       }
+                                       else if (value is Type)
+                                       {
+                                               // value.GetType() would return a subclass of Type, but we don't want to deal with that
+                                               type = u.System_Type;
+                                       }
+                                       else
+                                       {
+                                               type = u.Import(value.GetType());
+                                       }
+                                       WriteFieldOrPropType(type);
+                                       WriteFixedArg(type, value);
+                               }
+                               else if (type.IsArray)
+                               {
+                                       if (value == null)
+                                       {
+                                               WriteInt32(-1);
+                                       }
+                                       else
+                                       {
+                                               Array array = (Array)value;
+                                               Type elemType = type.GetElementType();
+                                               WriteInt32(array.Length);
+                                               foreach (object val in array)
+                                               {
+                                                       WriteFixedArg(elemType, val);
+                                               }
+                                       }
+                               }
+                               else if (type.IsEnum)
+                               {
+                                       WriteFixedArg(type.GetEnumUnderlyingTypeImpl(), value);
+                               }
+                               else
+                               {
+                                       switch (Type.GetTypeCode(type))
+                                       {
+                                               case TypeCode.Boolean:
+                                                       WriteByte((bool)value ? (byte)1 : (byte)0);
+                                                       break;
+                                               case TypeCode.Char:
+                                                       WriteUInt16((char)value);
+                                                       break;
+                                               case TypeCode.SByte:
+                                                       WriteByte((byte)(sbyte)value);
+                                                       break;
+                                               case TypeCode.Byte:
+                                                       WriteByte((byte)value);
+                                                       break;
+                                               case TypeCode.Int16:
+                                                       WriteUInt16((ushort)(short)value);
+                                                       break;
+                                               case TypeCode.UInt16:
+                                                       WriteUInt16((ushort)value);
+                                                       break;
+                                               case TypeCode.Int32:
+                                                       WriteInt32((int)value);
+                                                       break;
+                                               case TypeCode.UInt32:
+                                                       WriteInt32((int)(uint)value);
+                                                       break;
+                                               case TypeCode.Int64:
+                                                       WriteInt64((long)value);
+                                                       break;
+                                               case TypeCode.UInt64:
+                                                       WriteInt64((long)(ulong)value);
+                                                       break;
+                                               case TypeCode.Single:
+                                                       WriteSingle((float)value);
+                                                       break;
+                                               case TypeCode.Double:
+                                                       WriteDouble((double)value);
+                                                       break;
+                                               default:
+                                                       throw new ArgumentException();
+                                       }
+                               }
+                       }
+
+                       private void WriteInt64(long value)
+                       {
+                               bb.Write(value);
+                       }
+
+                       private void WriteSingle(float value)
+                       {
+                               bb.Write(value);
+                       }
+
+                       private void WriteDouble(double value)
+                       {
+                               bb.Write(value);
+                       }
+
+                       private void WriteTypeName(Type type)
+                       {
+                               string name = null;
+                               if (type != null)
+                               {
+                                       if (type.Assembly == moduleBuilder.Assembly)
+                                       {
+                                               name = type.FullName;
+                                       }
+                                       else
+                                       {
+                                               name = type.AssemblyQualifiedName;
+                                       }
+                               }
+                               WriteString(name);
+                       }
+
+                       private void WriteString(string val)
+                       {
+                               bb.Write(val);
+                       }
+
+                       private void WritePackedLen(int len)
+                       {
+                               bb.WriteCompressedInt(len);
+                       }
+
+                       private void WriteFieldOrPropType(Type type)
+                       {
+                               Universe u = type.Module.universe;
+                               if (type == u.System_Type)
+                               {
+                                       WriteByte(0x50);
+                               }
+                               else if (type == u.System_Object)
+                               {
+                                       WriteByte(0x51);
+                               }
+                               else if (type.IsArray)
+                               {
+                                       WriteByte(0x1D);
+                                       WriteFieldOrPropType(type.GetElementType());
+                               }
+                               else if (type.IsEnum)
+                               {
+                                       WriteByte(0x55);
+                                       WriteTypeName(type);
+                               }
+                               else
+                               {
+                                       switch (Type.GetTypeCode(type))
+                                       {
+                                               case TypeCode.Boolean:
+                                                       WriteByte(0x02);
+                                                       break;
+                                               case TypeCode.Char:
+                                                       WriteByte(0x03);
+                                                       break;
+                                               case TypeCode.SByte:
+                                                       WriteByte(0x04);
+                                                       break;
+                                               case TypeCode.Byte:
+                                                       WriteByte(0x05);
+                                                       break;
+                                               case TypeCode.Int16:
+                                                       WriteByte(0x06);
+                                                       break;
+                                               case TypeCode.UInt16:
+                                                       WriteByte(0x07);
+                                                       break;
+                                               case TypeCode.Int32:
+                                                       WriteByte(0x08);
+                                                       break;
+                                               case TypeCode.UInt32:
+                                                       WriteByte(0x09);
+                                                       break;
+                                               case TypeCode.Int64:
+                                                       WriteByte(0x0A);
+                                                       break;
+                                               case TypeCode.UInt64:
+                                                       WriteByte(0x0B);
+                                                       break;
+                                               case TypeCode.Single:
+                                                       WriteByte(0x0C);
+                                                       break;
+                                               case TypeCode.Double:
+                                                       WriteByte(0x0D);
+                                                       break;
+                                               case TypeCode.String:
+                                                       WriteByte(0x0E);
+                                                       break;
+                                               default:
+                                                       throw new ArgumentException();
+                                       }
+                               }
+                       }
+               }
+
+               internal bool IsPseudoCustomAttribute
+               {
+                       get { return con.DeclaringType.IsPseudoCustomAttribute; }
+               }
+
+               internal ConstructorInfo Constructor
+               {
+                       get { return con; }
+               }
+
+               internal int WriteBlob(ModuleBuilder moduleBuilder)
+               {
+                       ByteBuffer bb = new ByteBuffer(100);
+                       if (blob != null)
+                       {
+                               bb.Write(blob);
+                       }
+                       else
+                       {
+                               BlobWriter bw = new BlobWriter(moduleBuilder, this, bb);
+                               bw.WriteCustomAttributeBlob();
+                       }
+                       return moduleBuilder.Blobs.Add(bb);
+               }
+
+               internal object GetConstructorArgument(int pos)
+               {
+                       return constructorArgs[pos];
+               }
+
+               internal int ConstructorArgumentCount
+               {
+                       get { return constructorArgs == null ? 0 : constructorArgs.Length; }
+               }
+
+               internal T? GetFieldValue<T>(string name) where T : struct
+               {
+                       object val = GetFieldValue(name);
+                       if (val is T)
+                       {
+                               return (T)val;
+                       }
+                       else if (val != null)
+                       {
+                               if (typeof(T).IsEnum)
+                               {
+                                       Debug.Assert(Enum.GetUnderlyingType(typeof(T)) == val.GetType());
+                                       return (T)Enum.ToObject(typeof(T), val);
+                               }
+                               else
+                               {
+                                       Debug.Assert(Enum.GetUnderlyingType(val.GetType()) == typeof(T));
+                                       return (T)Convert.ChangeType(val, typeof(T));
+                               }
+                       }
+                       else
+                       {
+                               return null;
+                       }
+               }
+
+               internal object GetFieldValue(string name)
+               {
+                       if (namedFields != null)
+                       {
+                               for (int i = 0; i < namedFields.Length; i++)
+                               {
+                                       if (namedFields[i].Name == name)
+                                       {
+                                               return fieldValues[i];
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
+               internal void WriteNamedArgumentsForDeclSecurity(ModuleBuilder moduleBuilder, ByteBuffer bb)
+               {
+                       BlobWriter bw = new BlobWriter(moduleBuilder, this, bb);
+                       bw.WriteNamedArguments(true);
+               }
+
+               internal CustomAttributeData ToData(Assembly asm)
+               {
+                       if (blob != null)
+                       {
+                               return new CustomAttributeData(asm, con, new IKVM.Reflection.Reader.ByteReader(blob, 0, blob.Length));
+                       }
+                       else
+                       {
+                               List<CustomAttributeNamedArgument> namedArgs = new List<CustomAttributeNamedArgument>();
+                               if (namedProperties != null)
+                               {
+                                       for (int i = 0; i < namedProperties.Length; i++)
+                                       {
+                                               namedArgs.Add(new CustomAttributeNamedArgument(namedProperties[i], new CustomAttributeTypedArgument(namedProperties[i].PropertyType, propertyValues[i])));
+                                       }
+                               }
+                               if (namedFields != null)
+                               {
+                                       for (int i = 0; i < namedFields.Length; i++)
+                                       {
+                                               namedArgs.Add(new CustomAttributeNamedArgument(namedFields[i], new CustomAttributeTypedArgument(namedFields[i].FieldType, fieldValues[i])));
+                                       }
+                               }
+                               return new CustomAttributeData(con, constructorArgs, namedArgs);
+                       }
+               }
+
+               internal bool HasBlob
+               {
+                       get { return blob != null; }
+               }
+
+               internal CustomAttributeBuilder DecodeBlob(Assembly asm)
+               {
+                       if (blob == null)
+                       {
+                               return this;
+                       }
+                       else
+                       {
+                               return ToData(asm).__ToBuilder();
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/EnumBuilder.cs b/mcs/class/IKVM.Reflection/Emit/EnumBuilder.cs
new file mode 100644 (file)
index 0000000..5ad9686
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class EnumBuilder : Type
+       {
+               private readonly TypeBuilder typeBuilder;
+               private readonly FieldBuilder fieldBuilder;
+
+               internal EnumBuilder(TypeBuilder typeBuilder, FieldBuilder fieldBuilder)
+               {
+                       this.typeBuilder = typeBuilder;
+                       this.fieldBuilder = fieldBuilder;
+               }
+
+               public override Type UnderlyingSystemType
+               {
+                       get { return typeBuilder.UnderlyingSystemType; }
+               }
+
+               public override Type BaseType
+               {
+                       get { return typeBuilder.BaseType; }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return typeBuilder.Attributes; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeBuilder.Module; }
+               }
+
+               public FieldBuilder DefineLiteral(string literalName, object literalValue)
+               {
+                       FieldBuilder fb = typeBuilder.DefineField(literalName, typeBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
+                       fb.SetConstant(literalValue);
+                       return fb;
+               }
+
+               public Type CreateType()
+               {
+                       return typeBuilder.CreateType();
+               }
+
+               public TypeToken TypeToken
+               {
+                       get { return typeBuilder.TypeToken; }
+               }
+
+               public FieldBuilder UnderlyingField
+               {
+                       get { return fieldBuilder; }
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       typeBuilder.SetCustomAttribute(con, binaryAttribute);
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       typeBuilder.SetCustomAttribute(customBuilder);
+               }
+
+               public override Type GetEnumUnderlyingType()
+               {
+                       return fieldBuilder.FieldType;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/Enums.cs b/mcs/class/IKVM.Reflection/Emit/Enums.cs
new file mode 100644 (file)
index 0000000..7c85a55
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+namespace IKVM.Reflection.Emit
+{
+       public enum AssemblyBuilderAccess
+       {
+               Save = 2,
+               ReflectionOnly = 6,
+       }
+
+       public enum OpCodeType
+       {
+               Annotation = 0,
+               Macro = 1,
+               Nternal = 2,
+               Objmodel = 3,
+               Prefix = 4,
+               Primitive = 5,
+       }
+       
+       public enum OperandType
+       {
+               InlineBrTarget = 0,
+               InlineField = 1,
+               InlineI = 2,
+               InlineI8 = 3,
+               InlineMethod = 4,
+               InlineNone = 5,
+               InlinePhi = 6,
+               InlineR = 7,
+               InlineSig = 9,
+               InlineString = 10,
+               InlineSwitch = 11,
+               InlineTok = 12,
+               InlineType = 13,
+               InlineVar = 14,
+               ShortInlineBrTarget = 15,
+               ShortInlineI = 16,
+               ShortInlineR = 17,
+               ShortInlineVar = 18,
+       }
+
+       public enum FlowControl
+       {
+               Branch = 0,
+               Break = 1,
+               Call = 2,
+               Cond_Branch = 3,
+               Meta = 4,
+               Next = 5,
+               Return = 7,
+               Throw = 8,
+       }
+
+       public enum PackingSize
+       {
+               Unspecified = 0,
+               Size1 = 1,
+               Size2 = 2,
+               Size4 = 4,
+               Size8 = 8,
+               Size16 = 16,
+               Size32 = 32,
+               Size64 = 64,
+               Size128 = 128,
+       }
+
+       public enum PEFileKinds
+       {
+               Dll = 1,
+               ConsoleApplication = 2,
+               WindowApplication = 3,
+       }
+
+       public enum StackBehaviour
+       {
+               Pop0 = 0,
+               Pop1 = 1,
+               Pop1_pop1 = 2,
+               Popi = 3,
+               Popi_pop1 = 4,
+               Popi_popi = 5,
+               Popi_popi8 = 6,
+               Popi_popi_popi = 7,
+               Popi_popr4 = 8,
+               Popi_popr8 = 9,
+               Popref = 10,
+               Popref_pop1 = 11,
+               Popref_popi = 12,
+               Popref_popi_popi = 13,
+               Popref_popi_popi8 = 14,
+               Popref_popi_popr4 = 15,
+               Popref_popi_popr8 = 16,
+               Popref_popi_popref = 17,
+               Push0 = 18,
+               Push1 = 19,
+               Push1_push1 = 20,
+               Pushi = 21,
+               Pushi8 = 22,
+               Pushr4 = 23,
+               Pushr8 = 24,
+               Pushref = 25,
+               Varpop = 26,
+               Varpush = 27,
+               Popref_popi_pop1 = 28,
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/EventBuilder.cs b/mcs/class/IKVM.Reflection/Emit/EventBuilder.cs
new file mode 100644 (file)
index 0000000..be29644
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class EventBuilder : EventInfo
+       {
+               private readonly TypeBuilder typeBuilder;
+               private readonly string name;
+               private EventAttributes attributes;
+               private readonly int eventtype;
+               private MethodBuilder addOnMethod;
+               private MethodBuilder removeOnMethod;
+               private MethodBuilder fireMethod;
+               private List<MethodBuilder> otherMethods;
+               private int lazyPseudoToken;
+
+               internal EventBuilder(TypeBuilder typeBuilder, string name, EventAttributes attributes, Type eventtype)
+               {
+                       this.typeBuilder = typeBuilder;
+                       this.name = name;
+                       this.attributes = attributes;
+                       this.eventtype = typeBuilder.ModuleBuilder.GetTypeTokenForMemberRef(eventtype);
+               }
+
+               public void SetAddOnMethod(MethodBuilder mdBuilder)
+               {
+                       addOnMethod = mdBuilder;
+               }
+
+               public void SetRemoveOnMethod(MethodBuilder mdBuilder)
+               {
+                       removeOnMethod = mdBuilder;
+               }
+
+               public void SetRaiseMethod(MethodBuilder mdBuilder)
+               {
+                       fireMethod = mdBuilder;
+               }
+
+               public void AddOtherMethod(MethodBuilder mdBuilder)
+               {
+                       if (otherMethods == null)
+                       {
+                               otherMethods = new List<MethodBuilder>();
+                       }
+                       otherMethods.Add(mdBuilder);
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       Universe u = typeBuilder.ModuleBuilder.universe;
+                       if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+                       {
+                               attributes |= EventAttributes.SpecialName;
+                       }
+                       else
+                       {
+                               if (lazyPseudoToken == 0)
+                               {
+                                       lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+                               }
+                               typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder);
+                       }
+               }
+
+               public override EventAttributes Attributes
+               {
+                       get { return attributes; }
+               }
+
+               public override MethodInfo GetAddMethod(bool nonPublic)
+               {
+                       return nonPublic || (addOnMethod != null && addOnMethod.IsPublic) ? addOnMethod : null;
+               }
+
+               public override MethodInfo GetRemoveMethod(bool nonPublic)
+               {
+                       return nonPublic || (removeOnMethod != null && removeOnMethod.IsPublic) ? removeOnMethod : null;
+               }
+
+               public override MethodInfo GetRaiseMethod(bool nonPublic)
+               {
+                       return nonPublic || (fireMethod != null && fireMethod.IsPublic) ? fireMethod : null;
+               }
+
+               public override MethodInfo[] GetOtherMethods(bool nonPublic)
+               {
+                       List<MethodInfo> list = new List<MethodInfo>();
+                       if (otherMethods != null)
+                       {
+                               foreach (MethodInfo method in otherMethods)
+                               {
+                                       if (nonPublic || method.IsPublic)
+                                       {
+                                               list.Add(method);
+                                       }
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeBuilder; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeBuilder.ModuleBuilder; }
+               }
+
+               public EventToken GetEventToken()
+               {
+                       if (lazyPseudoToken == 0)
+                       {
+                               lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+                       }
+                       return new EventToken(lazyPseudoToken);
+               }
+
+               public override Type EventHandlerType
+               {
+                       get { return typeBuilder.ModuleBuilder.ResolveType(eventtype); }
+               }
+
+               internal void Bake()
+               {
+                       EventTable.Record rec = new EventTable.Record();
+                       rec.EventFlags = (short)attributes;
+                       rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name);
+                       rec.EventType = eventtype;
+                       int token = 0x14000000 | typeBuilder.ModuleBuilder.Event.AddRecord(rec);
+
+                       if (lazyPseudoToken != 0)
+                       {
+                               typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
+                       }
+
+                       if (addOnMethod != null)
+                       {
+                               AddMethodSemantics(MethodSemanticsTable.AddOn, addOnMethod.MetadataToken, token);
+                       }
+                       if (removeOnMethod != null)
+                       {
+                               AddMethodSemantics(MethodSemanticsTable.RemoveOn, removeOnMethod.MetadataToken, token);
+                       }
+                       if (fireMethod != null)
+                       {
+                               AddMethodSemantics(MethodSemanticsTable.Fire, fireMethod.MetadataToken, token);
+                       }
+                       if (otherMethods != null)
+                       {
+                               foreach (MethodBuilder method in otherMethods)
+                               {
+                                       AddMethodSemantics(MethodSemanticsTable.Other, method.MetadataToken, token);
+                               }
+                       }
+               }
+
+               private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
+               {
+                       MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record();
+                       rec.Semantics = semantics;
+                       rec.Method = methodToken;
+                       rec.Association = propertyToken;
+                       typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec);
+               }
+
+               internal override bool IsPublic
+               {
+                       get
+                       {
+                               if ((addOnMethod != null && addOnMethod.IsPublic) || (removeOnMethod != null && removeOnMethod.IsPublic) || (fireMethod != null && fireMethod.IsPublic))
+                               {
+                                       return true;
+                               }
+                               if (otherMethods != null)
+                               {
+                                       foreach (MethodBuilder method in otherMethods)
+                                       {
+                                               if (method.IsPublic)
+                                               {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               return false;
+                       }
+               }
+
+               internal override bool IsStatic
+               {
+                       get
+                       {
+                               if ((addOnMethod != null && addOnMethod.IsStatic) || (removeOnMethod != null && removeOnMethod.IsStatic) || (fireMethod != null && fireMethod.IsStatic))
+                               {
+                                       return true;
+                               }
+                               if (otherMethods != null)
+                               {
+                                       foreach (MethodBuilder method in otherMethods)
+                                       {
+                                               if (method.IsStatic)
+                                               {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               return false;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/FieldBuilder.cs b/mcs/class/IKVM.Reflection/Emit/FieldBuilder.cs
new file mode 100644 (file)
index 0000000..4316117
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.CompilerServices;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class FieldBuilder : FieldInfo
+       {
+               private readonly TypeBuilder typeBuilder;
+               private readonly string name;
+               private readonly int pseudoToken;
+               private FieldAttributes attribs;
+               private readonly int nameIndex;
+               private readonly int signature;
+               private readonly FieldSignature fieldSig;
+
+               internal FieldBuilder(TypeBuilder type, string name, Type fieldType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attribs)
+               {
+                       this.typeBuilder = type;
+                       this.name = name;
+                       this.pseudoToken = type.ModuleBuilder.AllocPseudoToken();
+                       this.nameIndex = type.ModuleBuilder.Strings.Add(name);
+                       this.fieldSig = FieldSignature.Create(fieldType, optionalCustomModifiers, requiredCustomModifiers);
+                       ByteBuffer sig = new ByteBuffer(5);
+                       fieldSig.WriteSig(this.typeBuilder.ModuleBuilder, sig);
+                       this.signature = this.typeBuilder.ModuleBuilder.Blobs.Add(sig);
+                       this.attribs = attribs;
+                       this.typeBuilder.ModuleBuilder.Field.AddVirtualRecord();
+               }
+
+               public void SetConstant(object defaultValue)
+               {
+                       attribs |= FieldAttributes.HasDefault;
+                       typeBuilder.ModuleBuilder.AddConstant(pseudoToken, defaultValue);
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       return typeBuilder.Module.Constant.GetRawConstantValue(typeBuilder.Module, this.MetadataToken);
+               }
+
+               public void __SetDataAndRVA(byte[] data)
+               {
+                       attribs |= FieldAttributes.HasFieldRVA;
+                       FieldRVATable.Record rec = new FieldRVATable.Record();
+                       rec.RVA = typeBuilder.ModuleBuilder.initializedData.Position;
+                       rec.Field = pseudoToken;
+                       typeBuilder.ModuleBuilder.FieldRVA.AddRecord(rec);
+                       typeBuilder.ModuleBuilder.initializedData.Write(data);
+               }
+
+               public override void __GetDataFromRVA(byte[] data, int offset, int length)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       Universe u = this.Module.universe;
+                       if (customBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_FieldOffsetAttribute)
+                       {
+                               customBuilder = customBuilder.DecodeBlob(this.Module.Assembly);
+                               SetOffset((int)customBuilder.GetConstructorArgument(0));
+                       }
+                       else if (customBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_MarshalAsAttribute)
+                       {
+                               MarshalSpec.SetMarshalAsAttribute(typeBuilder.ModuleBuilder, pseudoToken, customBuilder);
+                               attribs |= FieldAttributes.HasFieldMarshal;
+                       }
+                       else if (customBuilder.Constructor.DeclaringType == u.System_NonSerializedAttribute)
+                       {
+                               attribs |= FieldAttributes.NotSerialized;
+                       }
+                       else if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+                       {
+                               attribs |= FieldAttributes.SpecialName;
+                       }
+                       else
+                       {
+                               typeBuilder.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
+                       }
+               }
+
+               public void SetOffset(int iOffset)
+               {
+                       FieldLayoutTable.Record rec = new FieldLayoutTable.Record();
+                       rec.Offset = iOffset;
+                       rec.Field = pseudoToken;
+                       typeBuilder.ModuleBuilder.FieldLayout.AddRecord(rec);
+               }
+
+               public override FieldAttributes Attributes
+               {
+                       get { return attribs; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return pseudoToken; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeBuilder.Module; }
+               }
+
+               public FieldToken GetToken()
+               {
+                       return new FieldToken(pseudoToken);
+               }
+
+               internal void WriteFieldRecords(MetadataWriter mw)
+               {
+                       mw.Write((short)attribs);
+                       mw.WriteStringIndex(nameIndex);
+                       mw.WriteBlobIndex(signature);
+               }
+
+               internal void FixupToken(int token)
+               {
+                       typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token);
+               }
+
+               internal override FieldSignature FieldSignature
+               {
+                       get { return fieldSig; }
+               }
+
+               internal override int ImportTo(ModuleBuilder other)
+               {
+                       if (typeBuilder.IsGenericTypeDefinition)
+                       {
+                               return other.ImportMember(TypeBuilder.GetField(typeBuilder, this));
+                       }
+                       else if (other == typeBuilder.ModuleBuilder)
+                       {
+                               return pseudoToken;
+                       }
+                       else
+                       {
+                               return other.ImportMethodOrField(typeBuilder, name, fieldSig);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/ILGenerator.cs b/mcs/class/IKVM.Reflection/Emit/ILGenerator.cs
new file mode 100644 (file)
index 0000000..5a86d1f
--- /dev/null
@@ -0,0 +1,1143 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Diagnostics.SymbolStore;
+using System.Diagnostics;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public struct Label
+       {
+               // 1-based here, to make sure that an uninitialized Label isn't valid
+               private readonly int index1;
+
+               internal Label(int index)
+               {
+                       this.index1 = index + 1;
+               }
+
+               internal int Index
+               {
+                       get { return index1 - 1; }
+               }
+
+               public bool Equals(Label other)
+               {
+                       return other.index1 == index1;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return this == obj as Label?;
+               }
+
+               public override int GetHashCode()
+               {
+                       return index1;
+               }
+
+               public static bool operator ==(Label arg1, Label arg2)
+               {
+                       return arg1.index1 == arg2.index1;
+               }
+
+               public static bool operator !=(Label arg1, Label arg2)
+               {
+                       return !(arg1 == arg2);
+               }
+       }
+
+       public sealed class LocalBuilder
+       {
+               private readonly Type localType;
+               private readonly int index;
+               private readonly bool pinned;
+               internal string name;
+               internal int startOffset;
+               internal int endOffset;
+
+               internal LocalBuilder(Type localType, int index, bool pinned)
+               {
+                       this.localType = localType;
+                       this.index = index;
+                       this.pinned = pinned;
+               }
+
+               public void SetLocalSymInfo(string name)
+               {
+                       this.name = name;
+               }
+
+               public void SetLocalSymInfo(string name, int startOffset, int endOffset)
+               {
+                       this.name = name;
+                       this.startOffset = startOffset;
+                       this.endOffset = endOffset;
+               }
+
+               public Type LocalType
+               {
+                       get { return localType; }
+               }
+
+               public int LocalIndex
+               {
+                       get { return index; }
+               }
+
+               public bool IsPinned
+               {
+                       get { return pinned; }
+               }
+       }
+
+       public sealed class ILGenerator
+       {
+               private static readonly Type FAULT = new BakedType(null); // the type we use here doesn't matter, as long as it can never be used as a real exception type
+               private readonly ModuleBuilder moduleBuilder;
+               private readonly ByteBuffer code;
+               private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
+               private readonly List<int> tokenFixups = new List<int>();
+               private readonly List<int> labels = new List<int>();
+               private readonly List<int> labelStackHeight = new List<int>();
+               private readonly List<LabelFixup> labelFixups = new List<LabelFixup>();
+               private readonly List<SequencePoint> sequencePoints = new List<SequencePoint>();
+               private readonly List<ExceptionBlock> exceptions = new List<ExceptionBlock>();
+               private readonly Stack<ExceptionBlock> exceptionStack = new Stack<ExceptionBlock>();
+               private ushort maxStack;
+               private int stackHeight;
+               private Scope scope;
+               private byte exceptionBlockAssistanceMode = EBAM_COMPAT;
+               private const byte EBAM_COMPAT = 0;
+               private const byte EBAM_DISABLE = 1;
+               private const byte EBAM_CLEVER = 2;
+
+               private struct LabelFixup
+               {
+                       internal int label;
+                       internal int offset;
+               }
+
+               private sealed class ExceptionBlock : IComparer<ExceptionBlock>
+               {
+                       internal readonly int ordinal;
+                       internal Label labelEnd;
+                       internal int tryOffset;
+                       internal int tryLength;
+                       internal int handlerOffset;
+                       internal int handlerLength;
+                       internal Type exceptionType;    // null = finally block or handler with filter, FAULT = fault block
+                       internal int filterOffset;
+
+                       internal ExceptionBlock(int ordinal)
+                       {
+                               this.ordinal = ordinal;
+                       }
+
+                       int IComparer<ExceptionBlock>.Compare(ExceptionBlock x, ExceptionBlock y)
+                       {
+                               // Mono's sort insists on doing unnecessary comparisons
+                               if (x == y)
+                               {
+                                       return 0;
+                               }
+                               if (x.tryOffset >= y.handlerOffset && x.tryOffset + x.tryLength <= y.handlerOffset + y.handlerLength)
+                               {
+                                       return -1;
+                               }
+                               if (y.tryOffset >= x.handlerOffset && y.tryOffset + y.tryLength <= x.handlerOffset + x.handlerLength)
+                               {
+                                       return 1;
+                               }
+                               if (x.tryOffset == y.tryOffset && x.tryLength == y.tryLength)
+                               {
+                                       return x.ordinal < y.ordinal ? -1 : 1;
+                               }
+                               if (x.tryOffset + x.tryLength <= y.tryOffset)
+                               {
+                                       return -1;
+                               }
+                               if (y.tryOffset + y.tryLength <= x.tryOffset)
+                               {
+                                       return 1;
+                               }
+                               if (x.tryOffset > y.tryOffset || (x.tryOffset == y.tryOffset && x.tryLength < y.tryLength))
+                               {
+                                       return -1;
+                               }
+                               else
+                               {
+                                       return 1;
+                               }
+                       }
+               }
+
+               private struct SequencePoint
+               {
+                       internal ISymbolDocumentWriter document;
+                       internal int offset;
+                       internal int startLine;
+                       internal int startColumn;
+                       internal int endLine;
+                       internal int endColumn;
+               }
+
+               private sealed class Scope
+               {
+                       internal readonly Scope parent;
+                       internal readonly List<Scope> children = new List<Scope>();
+                       internal readonly List<LocalBuilder> locals = new List<LocalBuilder>();
+                       internal int startOffset;
+                       internal int endOffset;
+
+                       internal Scope(Scope parent)
+                       {
+                               this.parent = parent;
+                       }
+               }
+
+               internal ILGenerator(ModuleBuilder moduleBuilder, int initialCapacity)
+               {
+                       this.code = new ByteBuffer(initialCapacity);
+                       this.moduleBuilder = moduleBuilder;
+                       if (moduleBuilder.symbolWriter != null)
+                       {
+                               scope = new Scope(null);
+                       }
+               }
+
+               private bool IsLabelReachable(Label label)
+               {
+                       return labelStackHeight[label.Index] != -1;
+               }
+
+               // non-standard API
+               public void __DisableExceptionBlockAssistance()
+               {
+                       exceptionBlockAssistanceMode = EBAM_DISABLE;
+               }
+
+               // non-standard API
+               public void __CleverExceptionBlockAssistance()
+               {
+                       exceptionBlockAssistanceMode = EBAM_CLEVER;
+               }
+
+               // new in .NET 4.0
+               public int ILOffset
+               {
+                       get { return code.Position; }
+               }
+
+               public void BeginCatchBlock(Type exceptionType)
+               {
+                       ExceptionBlock block = exceptionStack.Peek();
+                       if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
+                       {
+                               if (exceptionType == null)
+                               {
+                                       Emit(OpCodes.Endfilter);
+                               }
+                               else
+                               {
+                                       Emit(OpCodes.Leave, block.labelEnd);
+                               }
+                       }
+                       stackHeight = 0;
+                       UpdateStack(1);
+                       if (block.tryLength == 0)
+                       {
+                               block.tryLength = code.Position - block.tryOffset;
+                       }
+                       else if (exceptionType != null)
+                       {
+                               block.handlerLength = code.Position - block.handlerOffset;
+                               exceptionStack.Pop();
+                               ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
+                               newBlock.labelEnd = block.labelEnd;
+                               newBlock.tryOffset = block.tryOffset;
+                               newBlock.tryLength = block.tryLength;
+                               block = newBlock;
+                               exceptions.Add(block);
+                               exceptionStack.Push(block);
+                       }
+                       block.handlerOffset = code.Position;
+                       block.exceptionType = exceptionType;
+               }
+
+               public Label BeginExceptionBlock()
+               {
+                       ExceptionBlock block = new ExceptionBlock(exceptions.Count);
+                       block.labelEnd = DefineLabel();
+                       block.tryOffset = code.Position;
+                       exceptionStack.Push(block);
+                       exceptions.Add(block);
+                       return block.labelEnd;
+               }
+
+               public void BeginExceptFilterBlock()
+               {
+                       ExceptionBlock block = BeginFinallyFilterFaultBlock();
+                       block.filterOffset = code.Position;
+                       UpdateStack(1);
+               }
+
+               public void BeginFaultBlock()
+               {
+                       ExceptionBlock block = BeginFinallyFilterFaultBlock();
+                       block.handlerOffset = code.Position;
+                       block.exceptionType = FAULT;
+               }
+
+               public void BeginFinallyBlock()
+               {
+                       ExceptionBlock block = BeginFinallyFilterFaultBlock();
+                       block.handlerOffset = code.Position;
+               }
+
+               private ExceptionBlock BeginFinallyFilterFaultBlock()
+               {
+                       ExceptionBlock block = exceptionStack.Peek();
+                       if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
+                       {
+                               Emit(OpCodes.Leave, block.labelEnd);
+                       }
+                       if (block.handlerOffset == 0)
+                       {
+                               block.tryLength = code.Position - block.tryOffset;
+                       }
+                       else
+                       {
+                               block.handlerLength = code.Position - block.handlerOffset;
+                               Label labelEnd;
+                               if (exceptionBlockAssistanceMode != EBAM_COMPAT)
+                               {
+                                       labelEnd = block.labelEnd;
+                               }
+                               else
+                               {
+                                       MarkLabel(block.labelEnd);
+                                       labelEnd = DefineLabel();
+                                       Emit(OpCodes.Leave, labelEnd);
+                               }
+                               exceptionStack.Pop();
+                               ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
+                               newBlock.labelEnd = labelEnd;
+                               newBlock.tryOffset = block.tryOffset;
+                               newBlock.tryLength = code.Position - block.tryOffset;
+                               block = newBlock;
+                               exceptions.Add(block);
+                               exceptionStack.Push(block);
+                       }
+                       stackHeight = 0;
+                       return block;
+               }
+
+               public void EndExceptionBlock()
+               {
+                       ExceptionBlock block = exceptionStack.Pop();
+                       if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
+                       {
+                               if (block.filterOffset != 0 || (block.exceptionType != null && block.exceptionType != FAULT))
+                               {
+                                       Emit(OpCodes.Leave, block.labelEnd);
+                               }
+                               else
+                               {
+                                       Emit(OpCodes.Endfinally);
+                               }
+                       }
+                       MarkLabel(block.labelEnd);
+                       block.handlerLength = code.Position - block.handlerOffset;
+               }
+
+               public void BeginScope()
+               {
+                       Scope newScope = new Scope(scope);
+                       scope.children.Add(newScope);
+                       scope = newScope;
+                       scope.startOffset = code.Position;
+               }
+
+               public void UsingNamespace(string usingNamespace)
+               {
+                       if (moduleBuilder.symbolWriter != null)
+                       {
+                               moduleBuilder.symbolWriter.UsingNamespace(usingNamespace);
+                       }
+               }
+
+               public LocalBuilder DeclareLocal(Type localType)
+               {
+                       return DeclareLocal(localType, false);
+               }
+
+               public LocalBuilder DeclareLocal(Type localType, bool pinned)
+               {
+                       LocalBuilder local = new LocalBuilder(localType, locals.Count, pinned);
+                       locals.Add(local);
+                       if (scope != null)
+                       {
+                               scope.locals.Add(local);
+                       }
+                       return local;
+               }
+
+               public Label DefineLabel()
+               {
+                       Label label = new Label(labels.Count);
+                       labels.Add(-1);
+                       labelStackHeight.Add(-1);
+                       return label;
+               }
+
+               public void Emit(OpCode opc)
+               {
+                       Debug.Assert(opc != OpCodes.Ret || (opc == OpCodes.Ret && stackHeight <= 1));
+                       if (opc.Value < 0)
+                       {
+                               code.Write((byte)(opc.Value >> 8));
+                       }
+                       code.Write((byte)opc.Value);
+                       switch (opc.FlowControl)
+                       {
+                               case FlowControl.Branch:
+                               case FlowControl.Break:
+                               case FlowControl.Return:
+                               case FlowControl.Throw:
+                                       stackHeight = -1;
+                                       break;
+                               default:
+                                       UpdateStack(opc.StackDiff);
+                                       break;
+                       }
+               }
+
+               private void UpdateStack(int stackdiff)
+               {
+                       if (stackHeight == -1)
+                       {
+                               // we're about to emit code that is either unreachable or reachable only via a backward branch
+                               stackHeight = 0;
+                       }
+                       Debug.Assert(stackHeight >= 0 && stackHeight <= ushort.MaxValue);
+                       stackHeight += stackdiff;
+                       Debug.Assert(stackHeight >= 0 && stackHeight <= ushort.MaxValue);
+                       maxStack = Math.Max(maxStack, (ushort)stackHeight);
+               }
+
+               public void Emit(OpCode opc, byte arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, double arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, FieldInfo field)
+               {
+                       Emit(opc);
+                       WriteToken(moduleBuilder.GetFieldToken(field));
+               }
+
+               public void Emit(OpCode opc, short arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, int arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, long arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, Label label)
+               {
+                       // We need special stackHeight handling for unconditional branches,
+                       // because the branch and next flows have differing stack heights.
+                       // Note that this assumes that unconditional branches do not push/pop.
+                       int flowStackHeight = this.stackHeight;
+                       Emit(opc);
+                       if (opc == OpCodes.Leave || opc == OpCodes.Leave_S)
+                       {
+                               flowStackHeight = 0;
+                       }
+                       else if (opc.FlowControl != FlowControl.Branch)
+                       {
+                               flowStackHeight = this.stackHeight;
+                       }
+                       // if the label has already been marked, we can emit the branch offset directly
+                       if (labels[label.Index] != -1)
+                       {
+                               if (labelStackHeight[label.Index] != flowStackHeight && (labelStackHeight[label.Index] != 0 || flowStackHeight != -1))
+                               {
+                                       // the "backward branch constraint" prohibits this, so we don't need to support it
+                                       throw new NotSupportedException("'Backward branch constraints' violated");
+                               }
+                               if (opc.OperandType == OperandType.ShortInlineBrTarget)
+                               {
+                                       WriteByteBranchOffset(labels[label.Index] - (code.Position + 1));
+                               }
+                               else
+                               {
+                                       code.Write(labels[label.Index] - (code.Position + 4));
+                               }
+                       }
+                       else
+                       {
+                               Debug.Assert(labelStackHeight[label.Index] == -1 || labelStackHeight[label.Index] == flowStackHeight || (flowStackHeight == -1 && labelStackHeight[label.Index] == 0));
+                               labelStackHeight[label.Index] = flowStackHeight;
+                               LabelFixup fix = new LabelFixup();
+                               fix.label = label.Index;
+                               fix.offset = code.Position;
+                               labelFixups.Add(fix);
+                               if (opc.OperandType == OperandType.ShortInlineBrTarget)
+                               {
+                                       code.Write((byte)1);
+                               }
+                               else
+                               {
+                                       code.Write(4);
+                               }
+                       }
+               }
+
+               private void WriteByteBranchOffset(int offset)
+               {
+                       if (offset < -128 || offset > 127)
+                       {
+                               throw new NotSupportedException("Branch offset of " + offset + " does not fit in one-byte branch target at position " + code.Position);
+                       }
+                       code.Write((byte)offset);
+               }
+
+               public void Emit(OpCode opc, Label[] labels)
+               {
+                       Emit(opc);
+                       LabelFixup fix = new LabelFixup();
+                       fix.label = -1;
+                       fix.offset = code.Position;
+                       labelFixups.Add(fix);
+                       code.Write(labels.Length);
+                       foreach (Label label in labels)
+                       {
+                               code.Write(label.Index);
+                               if (this.labels[label.Index] != -1)
+                               {
+                                       if (labelStackHeight[label.Index] != stackHeight)
+                                       {
+                                               // the "backward branch constraint" prohibits this, so we don't need to support it
+                                               throw new NotSupportedException();
+                                       }
+                               }
+                               else
+                               {
+                                       Debug.Assert(labelStackHeight[label.Index] == -1 || labelStackHeight[label.Index] == stackHeight);
+                                       labelStackHeight[label.Index] = stackHeight;
+                               }
+                       }
+               }
+
+               public void Emit(OpCode opc, LocalBuilder local)
+               {
+                       if ((opc == OpCodes.Ldloc || opc == OpCodes.Ldloca || opc == OpCodes.Stloc) && local.LocalIndex < 256)
+                       {
+                               if (opc == OpCodes.Ldloc)
+                               {
+                                       switch (local.LocalIndex)
+                                       {
+                                               case 0:
+                                                       Emit(OpCodes.Ldloc_0);
+                                                       break;
+                                               case 1:
+                                                       Emit(OpCodes.Ldloc_1);
+                                                       break;
+                                               case 2:
+                                                       Emit(OpCodes.Ldloc_2);
+                                                       break;
+                                               case 3:
+                                                       Emit(OpCodes.Ldloc_3);
+                                                       break;
+                                               default:
+                                                       Emit(OpCodes.Ldloc_S);
+                                                       code.Write((byte)local.LocalIndex);
+                                                       break;
+                                       }
+                               }
+                               else if (opc == OpCodes.Ldloca)
+                               {
+                                       Emit(OpCodes.Ldloca_S);
+                                       code.Write((byte)local.LocalIndex);
+                               }
+                               else if (opc == OpCodes.Stloc)
+                               {
+                                       switch (local.LocalIndex)
+                                       {
+                                               case 0:
+                                                       Emit(OpCodes.Stloc_0);
+                                                       break;
+                                               case 1:
+                                                       Emit(OpCodes.Stloc_1);
+                                                       break;
+                                               case 2:
+                                                       Emit(OpCodes.Stloc_2);
+                                                       break;
+                                               case 3:
+                                                       Emit(OpCodes.Stloc_3);
+                                                       break;
+                                               default:
+                                                       Emit(OpCodes.Stloc_S);
+                                                       code.Write((byte)local.LocalIndex);
+                                                       break;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               Emit(opc);
+                               switch (opc.OperandType)
+                               {
+                                       case OperandType.InlineVar:
+                                               code.Write((ushort)local.LocalIndex);
+                                               break;
+                                       case OperandType.ShortInlineVar:
+                                               code.Write((byte)local.LocalIndex);
+                                               break;
+                               }
+                       }
+               }
+
+               private void WriteToken(FieldToken token)
+               {
+                       if (token.IsPseudoToken)
+                       {
+                               tokenFixups.Add(code.Position);
+                       }
+                       code.Write(token.Token);
+               }
+
+               private void WriteToken(MethodToken token)
+               {
+                       if (token.IsPseudoToken)
+                       {
+                               tokenFixups.Add(code.Position);
+                       }
+                       code.Write(token.Token);
+               }
+
+               private void UpdateStack(OpCode opc, bool hasthis, Type returnType, int parameterCount)
+               {
+                       if (opc == OpCodes.Jmp)
+                       {
+                               stackHeight = -1;
+                       }
+                       else if (opc.FlowControl == FlowControl.Call)
+                       {
+                               int stackdiff = 0;
+                               if ((hasthis && opc != OpCodes.Newobj) || opc == OpCodes.Calli)
+                               {
+                                       // pop this
+                                       stackdiff--;
+                               }
+                               // pop parameters
+                               stackdiff -= parameterCount;
+                               if (returnType != moduleBuilder.universe.System_Void)
+                               {
+                                       // push return value
+                                       stackdiff++;
+                               }
+                               UpdateStack(stackdiff);
+                       }
+               }
+
+               public void Emit(OpCode opc, MethodInfo method)
+               {
+                       Emit(opc);
+                       WriteToken(moduleBuilder.GetMethodTokenForIL(method));
+                       UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount);
+               }
+
+               public void Emit(OpCode opc, ConstructorInfo constructor)
+               {
+                       Emit(opc, constructor.GetMethodInfo());
+               }
+
+               public void Emit(OpCode opc, sbyte arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, float arg)
+               {
+                       Emit(opc);
+                       code.Write(arg);
+               }
+
+               public void Emit(OpCode opc, string str)
+               {
+                       Emit(opc);
+                       code.Write(0x70000000 | moduleBuilder.UserStrings.Add(str));
+               }
+
+               public void Emit(OpCode opc, Type type)
+               {
+                       Emit(opc);
+                       if (opc == OpCodes.Ldtoken)
+                       {
+                               code.Write(moduleBuilder.GetTypeToken(type).Token);
+                       }
+                       else
+                       {
+                               code.Write(moduleBuilder.GetTypeTokenForMemberRef(type));
+                       }
+               }
+
+               public void Emit(OpCode opcode, SignatureHelper signature)
+               {
+                       Emit(opcode);
+                       UpdateStack(opcode, signature.HasThis, signature.ReturnType, signature.ParameterCount);
+                       code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(signature.GetSignature(moduleBuilder))));
+               }
+
+               public void EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes)
+               {
+                       if (optionalParameterTypes == null || optionalParameterTypes.Length == 0)
+                       {
+                               Emit(opc, method);
+                       }
+                       else
+                       {
+                               Emit(opc);
+                               UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount + optionalParameterTypes.Length);
+                               ByteBuffer sig = new ByteBuffer(16);
+                               method.MethodSignature.WriteMethodRefSig(moduleBuilder, sig, optionalParameterTypes);
+                               MemberRefTable.Record record = new MemberRefTable.Record();
+                               if (method.Module == moduleBuilder)
+                               {
+                                       record.Class = method.MetadataToken;
+                               }
+                               else
+                               {
+                                       record.Class = moduleBuilder.GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
+                               }
+                               record.Name = moduleBuilder.Strings.Add(method.Name);
+                               record.Signature = moduleBuilder.Blobs.Add(sig);
+                               code.Write(0x0A000000 | moduleBuilder.MemberRef.FindOrAddRecord(record));
+                       }
+               }
+
+               public void __EmitCall(OpCode opc, ConstructorInfo constructor, Type[] optionalParameterTypes)
+               {
+                       EmitCall(opc, constructor.GetMethodInfo(), optionalParameterTypes);
+               }
+
+               public void EmitCalli(OpCode opc, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       returnType = returnType ?? moduleBuilder.universe.System_Void;
+                       Emit(opc);
+                       UpdateStack(opc, false, returnType, parameterTypes.Length);
+                       ByteBuffer sig = new ByteBuffer(16);
+                       Signature.WriteStandAloneMethodSig(moduleBuilder, sig, callingConvention, returnType, parameterTypes);
+                       code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(sig)));
+               }
+
+               public void EmitCalli(OpCode opc, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+               {
+                       returnType = returnType ?? moduleBuilder.universe.System_Void;
+                       optionalParameterTypes = optionalParameterTypes ?? Type.EmptyTypes;
+                       Emit(opc);
+                       UpdateStack(opc, (callingConvention & CallingConventions.HasThis | CallingConventions.ExplicitThis) == CallingConventions.HasThis, returnType, parameterTypes.Length + optionalParameterTypes.Length);
+                       ByteBuffer sig = new ByteBuffer(16);
+                       Signature.WriteStandAloneMethodSig(moduleBuilder, sig, callingConvention, returnType, parameterTypes, optionalParameterTypes);
+                       code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(sig)));
+               }
+
+               public void EmitWriteLine(string text)
+               {
+                       Universe u = moduleBuilder.universe;
+                       Emit(OpCodes.Ldstr, text);
+                       Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("WriteLine", new Type[] { u.System_String }));
+               }
+
+               public void EmitWriteLine(FieldInfo field)
+               {
+                       Universe u = moduleBuilder.universe;
+                       Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("get_Out"));
+                       if (field.IsStatic)
+                       {
+                               Emit(OpCodes.Ldsfld, field);
+                       }
+                       else
+                       {
+                               Emit(OpCodes.Ldarg_0);
+                               Emit(OpCodes.Ldfld, field);
+                       }
+                       Emit(OpCodes.Callvirt, u.Import(typeof(System.IO.TextWriter)).GetMethod("WriteLine", new Type[] { field.FieldType }));
+               }
+
+               public void EmitWriteLine(LocalBuilder local)
+               {
+                       Universe u = moduleBuilder.universe;
+                       Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("get_Out"));
+                       Emit(OpCodes.Ldloc, local);
+                       Emit(OpCodes.Callvirt, u.Import(typeof(System.IO.TextWriter)).GetMethod("WriteLine", new Type[] { local.LocalType }));
+               }
+
+               public void EndScope()
+               {
+                       scope.endOffset = code.Position;
+                       scope = scope.parent;
+               }
+
+               public void MarkLabel(Label loc)
+               {
+                       Debug.Assert(stackHeight == -1 || labelStackHeight[loc.Index] == -1 || stackHeight == labelStackHeight[loc.Index]);
+                       labels[loc.Index] = code.Position;
+                       if (labelStackHeight[loc.Index] == -1)
+                       {
+                               if (stackHeight == -1)
+                               {
+                                       // We're at a location that can only be reached by a backward branch,
+                                       // so according to the "backward branch constraint" that must mean the stack is empty,
+                                       // but note that this may be an unused label followed by another label that is used and
+                                       // that does have a non-zero stack height, so we don't yet set stackHeight here.
+                                       labelStackHeight[loc.Index] = 0;
+                               }
+                               else
+                               {
+                                       labelStackHeight[loc.Index] = stackHeight;
+                               }
+                       }
+                       else
+                       {
+                               Debug.Assert(stackHeight == -1 || stackHeight == labelStackHeight[loc.Index]);
+                               stackHeight = labelStackHeight[loc.Index];
+                       }
+               }
+
+               public void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn)
+               {
+                       SequencePoint sp = new SequencePoint();
+                       sp.document = document;
+                       sp.offset = code.Position;
+                       sp.startLine = startLine;
+                       sp.startColumn = startColumn;
+                       sp.endLine = endLine;
+                       sp.endColumn = endColumn;
+                       sequencePoints.Add(sp);
+               }
+
+               public void ThrowException(Type excType)
+               {
+                       Emit(OpCodes.Newobj, excType.GetConstructor(Type.EmptyTypes));
+                       Emit(OpCodes.Throw);
+               }
+
+               internal int WriteBody(bool initLocals)
+               {
+                       if (moduleBuilder.symbolWriter != null)
+                       {
+                               Debug.Assert(scope != null && scope.parent == null);
+                               scope.endOffset = code.Position;
+                       }
+
+                       ResolveBranches();
+
+                       ByteBuffer bb = moduleBuilder.methodBodies;
+
+                       int localVarSigTok = 0;
+
+                       int rva;
+                       if (locals.Count == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64)
+                       {
+                               rva = WriteTinyHeaderAndCode(bb);
+                       }
+                       else
+                       {
+                               rva = WriteFatHeaderAndCode(bb, ref localVarSigTok, initLocals);
+                       }
+
+                       if (moduleBuilder.symbolWriter != null)
+                       {
+                               if (sequencePoints.Count != 0)
+                               {
+                                       ISymbolDocumentWriter document = sequencePoints[0].document;
+                                       int[] offsets = new int[sequencePoints.Count];
+                                       int[] lines = new int[sequencePoints.Count];
+                                       int[] columns = new int[sequencePoints.Count];
+                                       int[] endLines = new int[sequencePoints.Count];
+                                       int[] endColumns = new int[sequencePoints.Count];
+                                       for (int i = 0; i < sequencePoints.Count; i++)
+                                       {
+                                               if (sequencePoints[i].document != document)
+                                               {
+                                                       throw new NotImplementedException();
+                                               }
+                                               offsets[i] = sequencePoints[i].offset;
+                                               lines[i] = sequencePoints[i].startLine;
+                                               columns[i] = sequencePoints[i].startColumn;
+                                               endLines[i] = sequencePoints[i].endLine;
+                                               endColumns[i] = sequencePoints[i].endColumn;
+                                       }
+                                       moduleBuilder.symbolWriter.DefineSequencePoints(document, offsets, lines, columns, endLines, endColumns);
+                               }
+
+                               WriteScope(scope, localVarSigTok);
+                       }
+                       return rva;
+               }
+
+               private void ResolveBranches()
+               {
+                       foreach (LabelFixup fixup in labelFixups)
+                       {
+                               // is it a switch?
+                               if (fixup.label == -1)
+                               {
+                                       code.Position = fixup.offset;
+                                       int count = code.GetInt32AtCurrentPosition();
+                                       int offset = fixup.offset + 4 + 4 * count;
+                                       code.Position += 4;
+                                       for (int i = 0; i < count; i++)
+                                       {
+                                               int index = code.GetInt32AtCurrentPosition();
+                                               code.Write(labels[index] - offset);
+                                       }
+                               }
+                               else
+                               {
+                                       code.Position = fixup.offset;
+                                       byte size = code.GetByteAtCurrentPosition();
+                                       int branchOffset = labels[fixup.label] - (code.Position + size);
+                                       if (size == 1)
+                                       {
+                                               WriteByteBranchOffset(branchOffset);
+                                       }
+                                       else
+                                       {
+                                               code.Write(branchOffset);
+                                       }
+                               }
+                       }
+               }
+
+               private int WriteTinyHeaderAndCode(ByteBuffer bb)
+               {
+                       int rva = bb.Position;
+                       const byte CorILMethod_TinyFormat = 0x2;
+                       bb.Write((byte)(CorILMethod_TinyFormat | (code.Length << 2)));
+                       WriteCode(bb);
+                       return rva;
+               }
+
+               private int WriteFatHeaderAndCode(ByteBuffer bb, ref int localVarSigTok, bool initLocals)
+               {
+                       // fat headers require 4-byte alignment
+                       bb.Align(4);
+                       int rva = bb.Position;
+
+                       if (locals.Count != 0)
+                       {
+                               ByteBuffer localVarSig = new ByteBuffer(locals.Count + 2);
+                               Signature.WriteLocalVarSig(moduleBuilder, localVarSig, locals);
+                               localVarSigTok = 0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(localVarSig));
+                       }
+
+                       const byte CorILMethod_FatFormat = 0x03;
+                       const byte CorILMethod_MoreSects = 0x08;
+                       const byte CorILMethod_InitLocals = 0x10;
+
+                       short flagsAndSize = (short)(CorILMethod_FatFormat | (3 << 12));
+                       if (initLocals)
+                       {
+                               flagsAndSize |= CorILMethod_InitLocals;
+                       }
+
+                       if (exceptions.Count > 0)
+                       {
+                               flagsAndSize |= CorILMethod_MoreSects;
+                       }
+
+                       bb.Write(flagsAndSize);
+                       bb.Write(maxStack);
+                       bb.Write(code.Length);
+                       bb.Write(localVarSigTok);
+
+                       WriteCode(bb);
+
+                       if (exceptions.Count > 0)
+                       {
+                               bb.Align(4);
+
+                               bool fat = false;
+                               foreach (ExceptionBlock block in exceptions)
+                               {
+                                       if (block.tryOffset > 65535 || block.tryLength > 255 || block.handlerOffset > 65535 || block.handlerLength > 255)
+                                       {
+                                               fat = true;
+                                               break;
+                                       }
+                               }
+                               exceptions.Sort(exceptions[0]);
+                               if (exceptions.Count * 12 + 4 > 255)
+                               {
+                                       fat = true;
+                               }
+                               const byte CorILMethod_Sect_EHTable = 0x1;
+                               const byte CorILMethod_Sect_FatFormat = 0x40;
+                               const short COR_ILEXCEPTION_CLAUSE_EXCEPTION = 0x0000;
+                               const short COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001;
+                               const short COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002;
+                               const short COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004;
+
+                               if (fat)
+                               {
+                                       bb.Write((byte)(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat));
+                                       int dataSize = exceptions.Count * 24 + 4;
+                                       bb.Write((byte)dataSize);
+                                       bb.Write((short)(dataSize >> 8));
+                                       foreach (ExceptionBlock block in exceptions)
+                                       {
+                                               if (block.exceptionType == FAULT)
+                                               {
+                                                       bb.Write((int)COR_ILEXCEPTION_CLAUSE_FAULT);
+                                               }
+                                               else if (block.filterOffset != 0)
+                                               {
+                                                       bb.Write((int)COR_ILEXCEPTION_CLAUSE_FILTER);
+                                               }
+                                               else if (block.exceptionType != null)
+                                               {
+                                                       bb.Write((int)COR_ILEXCEPTION_CLAUSE_EXCEPTION);
+                                               }
+                                               else
+                                               {
+                                                       bb.Write((int)COR_ILEXCEPTION_CLAUSE_FINALLY);
+                                               }
+                                               bb.Write(block.tryOffset);
+                                               bb.Write(block.tryLength);
+                                               bb.Write(block.handlerOffset);
+                                               bb.Write(block.handlerLength);
+                                               if (block.exceptionType != null && block.exceptionType != FAULT)
+                                               {
+                                                       bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
+                                               }
+                                               else
+                                               {
+                                                       bb.Write(block.filterOffset);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       bb.Write(CorILMethod_Sect_EHTable);
+                                       bb.Write((byte)(exceptions.Count * 12 + 4));
+                                       bb.Write((short)0);
+                                       foreach (ExceptionBlock block in exceptions)
+                                       {
+                                               if (block.exceptionType == FAULT)
+                                               {
+                                                       bb.Write(COR_ILEXCEPTION_CLAUSE_FAULT);
+                                               }
+                                               else if (block.filterOffset != 0)
+                                               {
+                                                       bb.Write(COR_ILEXCEPTION_CLAUSE_FILTER);
+                                               }
+                                               else if (block.exceptionType != null)
+                                               {
+                                                       bb.Write(COR_ILEXCEPTION_CLAUSE_EXCEPTION);
+                                               }
+                                               else
+                                               {
+                                                       bb.Write(COR_ILEXCEPTION_CLAUSE_FINALLY);
+                                               }
+                                               bb.Write((short)block.tryOffset);
+                                               bb.Write((byte)block.tryLength);
+                                               bb.Write((short)block.handlerOffset);
+                                               bb.Write((byte)block.handlerLength);
+                                               if (block.exceptionType != null && block.exceptionType != FAULT)
+                                               {
+                                                       bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
+                                               }
+                                               else
+                                               {
+                                                       bb.Write(block.filterOffset);
+                                               }
+                                       }
+                               }
+                       }
+                       return rva;
+               }
+
+               private void WriteCode(ByteBuffer bb)
+               {
+                       int codeOffset = bb.Position;
+                       foreach (int fixup in this.tokenFixups)
+                       {
+                               moduleBuilder.tokenFixupOffsets.Add(fixup + codeOffset);
+                       }
+                       bb.Write(code);
+               }
+
+               private void WriteScope(Scope scope, int localVarSigTok)
+               {
+                       moduleBuilder.symbolWriter.OpenScope(scope.startOffset);
+                       foreach (LocalBuilder local in scope.locals)
+                       {
+                               if (local.name != null)
+                               {
+                                       int startOffset = local.startOffset;
+                                       int endOffset = local.endOffset;
+                                       if (startOffset == 0 && endOffset == 0)
+                                       {
+                                               startOffset = scope.startOffset;
+                                               endOffset = scope.endOffset;
+                                       }
+                                       moduleBuilder.symbolWriter.DefineLocalVariable2(local.name, 0, localVarSigTok, SymAddressKind.ILOffset, local.LocalIndex, 0, 0, startOffset, endOffset);
+                               }
+                       }
+                       foreach (Scope child in scope.children)
+                       {
+                               WriteScope(child, localVarSigTok);
+                       }
+                       moduleBuilder.symbolWriter.CloseScope(scope.endOffset);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/MethodBuilder.cs b/mcs/class/IKVM.Reflection/Emit/MethodBuilder.cs
new file mode 100644 (file)
index 0000000..a54e637
--- /dev/null
@@ -0,0 +1,693 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Diagnostics.SymbolStore;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class MethodBuilder : MethodInfo
+       {
+               private readonly TypeBuilder typeBuilder;
+               private readonly string name;
+               private readonly int nameIndex;
+               private readonly int pseudoToken;
+               private int signature;
+               private Type returnType;
+               private Type[] parameterTypes;
+               private Type[][][] modifiers;   // see PackedCustomModifiers
+               private MethodAttributes attributes;
+               private MethodImplAttributes implFlags;
+               private ILGenerator ilgen;
+               private int rva;
+               private readonly CallingConventions callingConvention;
+               private List<ParameterBuilder> parameters;
+               private GenericTypeParameterBuilder[] gtpb;
+               private List<CustomAttributeBuilder> declarativeSecurity;
+               private MethodSignature methodSignature;
+               private bool initLocals = true;
+
+               internal MethodBuilder(TypeBuilder typeBuilder, string name, MethodAttributes attributes, CallingConventions callingConvention)
+               {
+                       this.typeBuilder = typeBuilder;
+                       this.name = name;
+                       this.pseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+                       // because all the MethodBuilders constitute a virtual MethodDef table, we cannot allocate the string during WriteMethodDefRecord,
+                       // since by then the metadata has already been frozen
+                       this.nameIndex = typeBuilder.ModuleBuilder.Strings.Add(name);
+                       this.attributes = attributes;
+                       if ((attributes & MethodAttributes.Static) == 0)
+                       {
+                               callingConvention |= CallingConventions.HasThis;
+                       }
+                       this.callingConvention = callingConvention;
+               }
+
+               public ILGenerator GetILGenerator()
+               {
+                       return GetILGenerator(16);
+               }
+
+               public ILGenerator GetILGenerator(int streamSize)
+               {
+                       if (ilgen == null)
+                       {
+                               ilgen = new ILGenerator(typeBuilder.ModuleBuilder, streamSize);
+                       }
+                       return ilgen;
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               private void SetDllImportPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       CallingConvention? callingConvention = customBuilder.GetFieldValue<CallingConvention>("CallingConvention");
+                       CharSet? charSet = customBuilder.GetFieldValue<CharSet>("CharSet");
+                       SetDllImportPseudoCustomAttribute((string)customBuilder.GetConstructorArgument(0),
+                               (string)customBuilder.GetFieldValue("EntryPoint"),
+                               callingConvention,
+                               charSet,
+                               (bool?)customBuilder.GetFieldValue("BestFitMapping"),
+                               (bool?)customBuilder.GetFieldValue("ThrowOnUnmappableChar"),
+                               (bool?)customBuilder.GetFieldValue("SetLastError"),
+                               (bool?)customBuilder.GetFieldValue("PreserveSig"),
+                               (bool?)customBuilder.GetFieldValue("ExactSpelling"));
+               }
+
+               internal void SetDllImportPseudoCustomAttribute(string dllName, string entryName, CallingConvention? nativeCallConv, CharSet? nativeCharSet,
+                       bool? bestFitMapping, bool? throwOnUnmappableChar, bool? setLastError, bool? preserveSig, bool? exactSpelling)
+               {
+                       const short NoMangle = 0x0001;
+                       const short CharSetMask = 0x0006;
+                       const short CharSetNotSpec = 0x0000;
+                       const short CharSetAnsi = 0x0002;
+                       const short CharSetUnicode = 0x0004;
+                       const short CharSetAuto = 0x0006;
+                       const short SupportsLastError = 0x0040;
+                       const short CallConvMask = 0x0700;
+                       const short CallConvWinapi = 0x0100;
+                       const short CallConvCdecl = 0x0200;
+                       const short CallConvStdcall = 0x0300;
+                       const short CallConvThiscall = 0x0400;
+                       const short CallConvFastcall = 0x0500;
+                       // non-standard flags
+                       const short BestFitOn = 0x0010;
+                       const short BestFitOff = 0x0020;
+                       const short CharMapErrorOn = 0x1000;
+                       const short CharMapErrorOff = 0x2000;
+                       int name = this.nameIndex;
+                       short flags = CharSetNotSpec | CallConvWinapi;
+                       if (bestFitMapping.HasValue)
+                       {
+                               flags |= bestFitMapping.Value ? BestFitOn : BestFitOff;
+                       }
+                       if (throwOnUnmappableChar.HasValue)
+                       {
+                               flags |= throwOnUnmappableChar.Value ? CharMapErrorOn : CharMapErrorOff;
+                       }
+                       if (nativeCallConv.HasValue)
+                       {
+                               flags &= ~CallConvMask;
+                               switch (nativeCallConv.Value)
+                               {
+                                       case System.Runtime.InteropServices.CallingConvention.Cdecl:
+                                               flags |= CallConvCdecl;
+                                               break;
+                                       case System.Runtime.InteropServices.CallingConvention.FastCall:
+                                               flags |= CallConvFastcall;
+                                               break;
+                                       case System.Runtime.InteropServices.CallingConvention.StdCall:
+                                               flags |= CallConvStdcall;
+                                               break;
+                                       case System.Runtime.InteropServices.CallingConvention.ThisCall:
+                                               flags |= CallConvThiscall;
+                                               break;
+                                       case System.Runtime.InteropServices.CallingConvention.Winapi:
+                                               flags |= CallConvWinapi;
+                                               break;
+                               }
+                       }
+                       if (nativeCharSet.HasValue)
+                       {
+                               flags &= ~CharSetMask;
+                               switch (nativeCharSet.Value)
+                               {
+                                       case CharSet.Ansi:
+                                       case CharSet.None:
+                                               flags |= CharSetAnsi;
+                                               break;
+                                       case CharSet.Auto:
+                                               flags |= CharSetAuto;
+                                               break;
+                                       case CharSet.Unicode:
+                                               flags |= CharSetUnicode;
+                                               break;
+                               }
+                       }
+                       if (entryName != null)
+                       {
+                               name = this.ModuleBuilder.Strings.Add(entryName);
+                       }
+                       if (exactSpelling.HasValue && exactSpelling.Value)
+                       {
+                               flags |= NoMangle;
+                       }
+                       if (!preserveSig.HasValue || preserveSig.Value)
+                       {
+                               implFlags |= MethodImplAttributes.PreserveSig;
+                       }
+                       if (setLastError.HasValue && setLastError.Value)
+                       {
+                               flags |= SupportsLastError;
+                       }
+                       ImplMapTable.Record rec = new ImplMapTable.Record();
+                       rec.MappingFlags = flags;
+                       rec.MemberForwarded = pseudoToken;
+                       rec.ImportName = name;
+                       rec.ImportScope = this.ModuleBuilder.ModuleRef.FindOrAddRecord(dllName == null ? 0 : this.ModuleBuilder.Strings.Add(dllName));
+                       this.ModuleBuilder.ImplMap.AddRecord(rec);
+               }
+
+               private void SetMethodImplAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       MethodImplOptions opt;
+                       switch (customBuilder.Constructor.ParameterCount)
+                       {
+                               case 0:
+                                       opt = 0;
+                                       break;
+                               case 1:
+                                       {
+                                               object val = customBuilder.GetConstructorArgument(0);
+                                               if (val is short)
+                                               {
+                                                       opt = (MethodImplOptions)(short)val;
+                                               }
+                                               else if (val is int)
+                                               {
+                                                       opt = (MethodImplOptions)(int)val;
+                                               }
+                                               else
+                                               {
+                                                       opt = (MethodImplOptions)val;
+                                               }
+                                               break;
+                                       }
+                               default:
+                                       throw new NotSupportedException();
+                       }
+                       MethodCodeType? type = customBuilder.GetFieldValue<MethodCodeType>("MethodCodeType");
+                       implFlags = (MethodImplAttributes)opt;
+                       if (type.HasValue)
+                       {
+                               implFlags |= (MethodImplAttributes)type;
+                       }
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       Universe u = this.ModuleBuilder.universe;
+                       Type type = customBuilder.Constructor.DeclaringType;
+                       if (type == u.System_Runtime_InteropServices_DllImportAttribute)
+                       {
+                               attributes |= MethodAttributes.PinvokeImpl;
+                               SetDllImportPseudoCustomAttribute(customBuilder.DecodeBlob(this.Module.Assembly));
+                       }
+                       else if (type == u.System_Runtime_CompilerServices_MethodImplAttribute)
+                       {
+                               SetMethodImplAttribute(customBuilder.DecodeBlob(this.Module.Assembly));
+                       }
+                       else if (type == u.System_Runtime_InteropServices_PreserveSigAttribute)
+                       {
+                               implFlags |= MethodImplAttributes.PreserveSig;
+                       }
+                       else if (type == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+                       {
+                               attributes |= MethodAttributes.SpecialName;
+                       }
+                       else
+                       {
+                               if (type == u.System_Security_SuppressUnmanagedCodeSecurityAttribute)
+                               {
+                                       attributes |= MethodAttributes.HasSecurity;
+                               }
+                               this.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
+                       }
+               }
+
+               public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+               {
+                       attributes |= MethodAttributes.HasSecurity;
+                       if (declarativeSecurity == null)
+                       {
+                               declarativeSecurity = new List<CustomAttributeBuilder>();
+                       }
+                       declarativeSecurity.Add(customBuilder);
+               }
+
+               public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+               {
+                       this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, securityAction, permissionSet);
+                       this.attributes |= MethodAttributes.HasSecurity;
+               }
+
+               public void SetImplementationFlags(MethodImplAttributes attributes)
+               {
+                       implFlags = attributes;
+               }
+
+               public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
+               {
+                       // the parameter is named "position", but it is actually a sequence number (i.e. 0 = return parameter, 1 = first parameter)
+                       int sequence = position--;
+                       if (parameters == null)
+                       {
+                               parameters = new List<ParameterBuilder>();
+                       }
+                       this.ModuleBuilder.Param.AddVirtualRecord();
+                       ParameterBuilder pb = new ParameterBuilder(this.ModuleBuilder, sequence, attributes, strParamName);
+                       if (parameters.Count == 0 || position > parameters[parameters.Count - 1].Position)
+                       {
+                               parameters.Add(pb);
+                       }
+                       else
+                       {
+                               for (int i = 0; i < parameters.Count; i++)
+                               {
+                                       if (parameters[i].Position > position)
+                                       {
+                                               parameters.Insert(i, pb);
+                                               break;
+                                       }
+                               }
+                       }
+                       return pb;
+               }
+
+               public void SetParameters(params Type[] parameterTypes)
+               {
+                       this.parameterTypes = Util.Copy(parameterTypes);
+               }
+
+               public void SetReturnType(Type returnType)
+               {
+                       this.returnType = returnType ?? this.Module.universe.System_Void;
+               }
+
+               public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       this.returnType = returnType ?? this.Module.universe.System_Void;
+                       this.parameterTypes = Util.Copy(parameterTypes);
+                       this.modifiers = PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
+                               parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, this.parameterTypes.Length);
+               }
+
+               public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+               {
+                       gtpb = new GenericTypeParameterBuilder[names.Length];
+                       for (int i = 0; i < names.Length; i++)
+                       {
+                               gtpb[i] = new GenericTypeParameterBuilder(names[i], null, this, i);
+                       }
+                       return (GenericTypeParameterBuilder[])gtpb.Clone();
+               }
+
+               public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+               {
+                       return new GenericMethodInstance(typeBuilder, this, typeArguments);
+               }
+
+               public override MethodInfo GetGenericMethodDefinition()
+               {
+                       if (gtpb == null)
+                       {
+                               throw new InvalidOperationException();
+                       }
+                       return this;
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       return Util.Copy(gtpb);
+               }
+
+               internal override Type GetGenericMethodArgument(int index)
+               {
+                       return gtpb[index];
+               }
+
+               internal override int GetGenericMethodArgumentCount()
+               {
+                       return gtpb == null ? 0 : gtpb.Length;
+               }
+
+               public override Type ReturnType
+               {
+                       get { return returnType; }
+               }
+
+               public override ParameterInfo ReturnParameter
+               {
+                       get { return new ParameterInfoImpl(this, -1); }
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { return attributes; }
+               }
+
+               public void __SetAttributes(MethodAttributes attributes)
+               {
+                       this.attributes = attributes;
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       return implFlags;
+               }
+
+               private sealed class ParameterInfoImpl : ParameterInfo
+               {
+                       private readonly MethodBuilder method;
+                       private readonly int parameter;
+
+                       internal ParameterInfoImpl(MethodBuilder method, int parameter)
+                       {
+                               this.method = method;
+                               this.parameter = parameter;
+                       }
+
+                       private ParameterBuilder ParameterBuilder
+                       {
+                               get
+                               {
+                                       if (method.parameters != null)
+                                       {
+                                               foreach (ParameterBuilder pb in method.parameters)
+                                               {
+                                                       if (pb.Position == parameter)
+                                                       {
+                                                               return pb;
+                                                       }
+                                               }
+                                       }
+                                       return null;
+                               }
+                       }
+
+                       public override string Name
+                       {
+                               get
+                               {
+                                       ParameterBuilder pb = this.ParameterBuilder;
+                                       return pb != null ? pb.Name : null;
+                               }
+                       }
+
+                       public override Type ParameterType
+                       {
+                               get { return parameter == -1 ? method.returnType : method.parameterTypes[parameter]; }
+                       }
+
+                       public override ParameterAttributes Attributes
+                       {
+                               get
+                               {
+                                       ParameterBuilder pb = this.ParameterBuilder;
+                                       return pb != null ? (ParameterAttributes)pb.Attributes : ParameterAttributes.None;
+                               }
+                       }
+
+                       public override int Position
+                       {
+                               get { return parameter; }
+                       }
+
+                       public override object RawDefaultValue
+                       {
+                               get
+                               {
+                                       ParameterBuilder pb = this.ParameterBuilder;
+                                       if (pb != null && (pb.Attributes & (int)ParameterAttributes.HasDefault) != 0)
+                                       {
+                                               return method.ModuleBuilder.Constant.GetRawConstantValue(method.ModuleBuilder, pb.PseudoToken);
+                                       }
+                                       if (pb != null && (pb.Attributes & (int)ParameterAttributes.Optional) != 0)
+                                       {
+                                               return Missing.Value;
+                                       }
+                                       return null;
+                               }
+                       }
+
+                       private Type[] GetCustomModifiers(int optOrReq)
+                       {
+                               if (method.modifiers == null || method.modifiers[parameter + 1] == null)
+                               {
+                                       return Type.EmptyTypes;
+                               }
+                               return Util.Copy(method.modifiers[parameter + 1][optOrReq]);
+                       }
+
+                       public override Type[] GetOptionalCustomModifiers()
+                       {
+                               return GetCustomModifiers(0);
+                       }
+
+                       public override Type[] GetRequiredCustomModifiers()
+                       {
+                               return GetCustomModifiers(1);
+                       }
+
+                       public override MemberInfo Member
+                       {
+                               get { return method; }
+                       }
+
+                       public override int MetadataToken
+                       {
+                               get
+                               {
+                                       ParameterBuilder pb = this.ParameterBuilder;
+                                       return pb != null ? pb.PseudoToken : 0x08000000;
+                               }
+                       }
+
+                       internal override Module Module
+                       {
+                               get { return method.Module; }
+                       }
+               }
+
+               public override ParameterInfo[] GetParameters()
+               {
+                       ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length];
+                       for (int i = 0; i < parameters.Length; i++)
+                       {
+                               parameters[i] = new ParameterInfoImpl(this, i);
+                       }
+                       return parameters;
+               }
+
+               internal override int ParameterCount
+               {
+                       get { return parameterTypes.Length; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override CallingConventions CallingConvention
+               {
+                       get { return callingConvention; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return pseudoToken; }
+               }
+
+               public override bool IsGenericMethod
+               {
+                       get { return gtpb != null; }
+               }
+
+               public override bool IsGenericMethodDefinition
+               {
+                       get { return gtpb != null; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeBuilder.Module; }
+               }
+
+               public Module GetModule()
+               {
+                       return typeBuilder.Module;
+               }
+
+               public MethodToken GetToken()
+               {
+                       return new MethodToken(pseudoToken);
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       throw new NotSupportedException();
+               }
+
+               public bool InitLocals
+               {
+                       get { return initLocals; }
+                       set { initLocals = value; }
+               }
+
+               internal void Bake()
+               {
+                       this.signature = this.ModuleBuilder.GetSignatureBlobIndex(this.MethodSignature);
+
+                       if (ilgen != null)
+                       {
+                               if (this.ModuleBuilder.symbolWriter != null)
+                               {
+                                       this.ModuleBuilder.symbolWriter.OpenMethod(new SymbolToken(-pseudoToken | 0x06000000));
+                               }
+                               rva = ilgen.WriteBody(initLocals);
+                               if (this.ModuleBuilder.symbolWriter != null)
+                               {
+                                       this.ModuleBuilder.symbolWriter.CloseMethod();
+                               }
+                               ilgen = null;
+                       }
+                       else
+                       {
+                               rva = -1;
+                       }
+
+                       if (declarativeSecurity != null)
+                       {
+                               this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, declarativeSecurity);
+                       }
+               }
+
+               internal ModuleBuilder ModuleBuilder
+               {
+                       get { return typeBuilder.ModuleBuilder; }
+               }
+
+               internal void WriteMethodDefRecord(int baseRVA, MetadataWriter mw, ref int paramList)
+               {
+                       if (rva != -1)
+                       {
+                               mw.Write(rva + baseRVA);
+                       }
+                       else
+                       {
+                               mw.Write(0);
+                       }
+                       mw.Write((short)implFlags);
+                       mw.Write((short)attributes);
+                       mw.WriteStringIndex(nameIndex);
+                       mw.WriteBlobIndex(signature);
+                       mw.WriteParam(paramList);
+                       if (parameters != null)
+                       {
+                               paramList += parameters.Count;
+                       }
+               }
+
+               internal void WriteParamRecords(MetadataWriter mw)
+               {
+                       if (parameters != null)
+                       {
+                               foreach (ParameterBuilder pb in parameters)
+                               {
+                                       pb.WriteParamRecord(mw);
+                               }
+                       }
+               }
+
+               internal void FixupToken(int token, ref int parameterToken)
+               {
+                       typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token);
+                       if (parameters != null)
+                       {
+                               foreach (ParameterBuilder pb in parameters)
+                               {
+                                       pb.FixupToken(parameterToken++);
+                               }
+                       }
+               }
+
+               internal override MethodSignature MethodSignature
+               {
+                       get
+                       {
+                               if (methodSignature == null)
+                               {
+                                       methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, modifiers, callingConvention, gtpb == null ? 0 : gtpb.Length);
+                               }
+                               return methodSignature;
+                       }
+               }
+
+               internal override int ImportTo(ModuleBuilder other)
+               {
+                       if (typeBuilder.IsGenericTypeDefinition)
+                       {
+                               return other.ImportMember(TypeBuilder.GetMethod(typeBuilder, this));
+                       }
+                       else if (other == typeBuilder.ModuleBuilder)
+                       {
+                               return pseudoToken;
+                       }
+                       else
+                       {
+                               return other.ImportMethodOrField(typeBuilder, name, this.MethodSignature);
+                       }
+               }
+
+               internal void CheckBaked()
+               {
+                       typeBuilder.CheckBaked();
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/ModuleBuilder.cs b/mcs/class/IKVM.Reflection/Emit/ModuleBuilder.cs
new file mode 100644 (file)
index 0000000..07dc278
--- /dev/null
@@ -0,0 +1,1364 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Diagnostics;
+using System.Diagnostics.SymbolStore;
+using System.Security.Cryptography;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class ModuleBuilder : Module, ITypeOwner
+       {
+               private static readonly bool usePublicKeyAssemblyReference = false;
+               private readonly Guid mvid = Guid.NewGuid();
+               private long imageBaseAddress = 0x00400000;
+               private readonly AssemblyBuilder asm;
+               internal readonly string moduleName;
+               internal readonly string fileName;
+               internal readonly ISymbolWriterImpl symbolWriter;
+               private readonly TypeBuilder moduleType;
+               private readonly List<TypeBuilder> types = new List<TypeBuilder>();
+               private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
+               private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
+               private readonly Dictionary<string, TypeBuilder> fullNameToType = new Dictionary<string, TypeBuilder>();
+               internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024);
+               internal readonly List<int> tokenFixupOffsets = new List<int>();
+               internal readonly ByteBuffer initializedData = new ByteBuffer(512);
+               internal readonly ByteBuffer manifestResources = new ByteBuffer(512);
+               internal ResourceSection unmanagedResources;
+               private readonly Dictionary<MemberInfo, int> importedMembers = new Dictionary<MemberInfo, int>();
+               private readonly Dictionary<MemberRefKey, int> importedMemberRefs = new Dictionary<MemberRefKey, int>();
+               private readonly Dictionary<Assembly, int> referencedAssemblies = new Dictionary<Assembly, int>();
+               private List<AssemblyName> referencedAssemblyNames;
+               private int nextPseudoToken = -1;
+               private readonly List<int> resolvedTokens = new List<int>();
+               internal readonly TableHeap Tables = new TableHeap();
+               internal readonly StringHeap Strings = new StringHeap();
+               internal readonly UserStringHeap UserStrings = new UserStringHeap();
+               internal readonly GuidHeap Guids = new GuidHeap();
+               internal readonly BlobHeap Blobs = new BlobHeap();
+
+               struct MemberRefKey : IEquatable<MemberRefKey>
+               {
+                       private readonly Type type;
+                       private readonly string name;
+                       private readonly Signature signature;
+
+                       internal MemberRefKey(Type type, string name, Signature signature)
+                       {
+                               this.type = type;
+                               this.name = name;
+                               this.signature = signature;
+                       }
+
+                       public bool Equals(MemberRefKey other)
+                       {
+                               return other.type.Equals(type)
+                                       && other.name == name
+                                       && other.signature.Equals(signature);
+                       }
+
+                       public override bool Equals(object obj)
+                       {
+                               MemberRefKey? other = obj as MemberRefKey?;
+                               return other != null && Equals(other);
+                       }
+
+                       public override int GetHashCode()
+                       {
+                               return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
+                       }
+               }
+
+               internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
+                       : base(asm.universe)
+               {
+                       this.asm = asm;
+                       this.moduleName = moduleName;
+                       this.fileName = fileName;
+                       if (emitSymbolInfo)
+                       {
+                               symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
+                       }
+                       // <Module> must be the first record in the TypeDef table
+                       moduleType = new TypeBuilder(this, "<Module>", null, 0);
+                       types.Add(moduleType);
+               }
+
+               internal void PopulatePropertyAndEventTables()
+               {
+                       // LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
+                       // but .NET sorts them and Mono requires them to be sorted, so we have to populate the
+                       // tables in the right order
+                       foreach (TypeBuilder type in types)
+                       {
+                               type.PopulatePropertyAndEventTables();
+                       }
+               }
+
+               internal void WriteTypeDefTable(MetadataWriter mw)
+               {
+                       int fieldList = 1;
+                       int methodList = 1;
+                       foreach (TypeBuilder type in types)
+                       {
+                               type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
+                       }
+               }
+
+               internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
+               {
+                       int paramList = 1;
+                       foreach (TypeBuilder type in types)
+                       {
+                               type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
+                       }
+               }
+
+               internal void WriteParamTable(MetadataWriter mw)
+               {
+                       foreach (TypeBuilder type in types)
+                       {
+                               type.WriteParamRecords(mw);
+                       }
+               }
+
+               internal void WriteFieldTable(MetadataWriter mw)
+               {
+                       foreach (TypeBuilder type in types)
+                       {
+                               type.WriteFieldRecords(mw);
+                       }
+               }
+
+               internal int AllocPseudoToken()
+               {
+                       return nextPseudoToken--;
+               }
+
+               public TypeBuilder DefineType(string name)
+               {
+                       return DefineType(name, TypeAttributes.Class);
+               }
+
+               public TypeBuilder DefineType(string name, TypeAttributes attr)
+               {
+                       return DefineType(name, attr, null);
+               }
+
+               public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
+               {
+                       return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
+               }
+
+               public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
+               {
+                       return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
+               }
+
+               public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
+               {
+                       return DefineType(name, attr, parent, packsize, 0);
+               }
+
+               public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
+               {
+                       TypeBuilder tb = DefineType(name, attr, parent);
+                       foreach (Type iface in interfaces)
+                       {
+                               tb.AddInterfaceImplementation(iface);
+                       }
+                       return tb;
+               }
+
+               public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
+               {
+                       if (parent == null && (attr & TypeAttributes.Interface) == 0)
+                       {
+                               parent = universe.System_Object;
+                       }
+                       TypeBuilder typeBuilder = new TypeBuilder(this, name, parent, attr);
+                       PostDefineType(typeBuilder, packingSize, typesize);
+                       return typeBuilder;
+               }
+
+               public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
+               {
+                       TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
+                       FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
+                       return new EnumBuilder(tb, fb);
+               }
+
+               internal TypeBuilder DefineNestedTypeHelper(TypeBuilder enclosingType, string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
+               {
+                       if (parent == null && (attr & TypeAttributes.Interface) == 0)
+                       {
+                               parent = universe.System_Object;
+                       }
+                       TypeBuilder typeBuilder = new TypeBuilder(enclosingType, name, parent, attr);
+                       PostDefineType(typeBuilder, packingSize, typesize);
+                       if (enclosingType != null)
+                       {
+                               NestedClassTable.Record rec = new NestedClassTable.Record();
+                               rec.NestedClass = typeBuilder.MetadataToken;
+                               rec.EnclosingClass = enclosingType.MetadataToken;
+                               this.NestedClass.AddRecord(rec);
+                       }
+                       return typeBuilder;
+               }
+
+               private void PostDefineType(TypeBuilder typeBuilder, PackingSize packingSize, int typesize)
+               {
+                       types.Add(typeBuilder);
+                       fullNameToType.Add(typeBuilder.FullName, typeBuilder);
+                       if (packingSize != PackingSize.Unspecified || typesize != 0)
+                       {
+                               ClassLayoutTable.Record rec = new ClassLayoutTable.Record();
+                               rec.PackingSize = (short)packingSize;
+                               rec.ClassSize = typesize;
+                               rec.Parent = typeBuilder.MetadataToken;
+                               this.ClassLayout.AddRecord(rec);
+                       }
+               }
+
+               public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
+               {
+                       return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
+               }
+
+               public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
+               {
+                       return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
+               }
+
+               public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
+               {
+                       return moduleType.DefineUninitializedData(name, size, attributes);
+               }
+
+               public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
+               {
+                       return moduleType.DefineInitializedData(name, data, attributes);
+               }
+
+               public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
+               {
+                       return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
+               }
+
+               public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
+               }
+
+               public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+               {
+                       return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+               }
+
+               public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+               {
+                       return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
+               }
+
+               public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+               {
+                       return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
+               }
+
+               public void CreateGlobalFunctions()
+               {
+                       moduleType.CreateType();
+               }
+
+               internal void AddTypeForwarder(Type type)
+               {
+                       ExportType(type);
+                       foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
+                       {
+                               // we export all nested types (i.e. even the private ones)
+                               // (this behavior is the same as the C# compiler)
+                               AddTypeForwarder(nested);
+                       }
+               }
+
+               private int ExportType(Type type)
+               {
+                       ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
+                       rec.TypeDefId = type.MetadataToken;
+                       rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+                       if (type.IsNested)
+                       {
+                               rec.Flags = 0;
+                               rec.TypeNamespace = 0;
+                               rec.Implementation = ExportType(type.DeclaringType);
+                       }
+                       else
+                       {
+                               rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
+                               string ns = type.Namespace;
+                               rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
+                               rec.Implementation = ImportAssemblyRef(type.Assembly);
+                       }
+                       return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       SetCustomAttribute(0x00000001, customBuilder);
+               }
+
+               internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
+               {
+                       Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
+                       CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
+                       rec.Parent = token;
+                       rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
+                       rec.Value = customBuilder.WriteBlob(this);
+                       this.CustomAttribute.AddRecord(rec);
+               }
+
+               internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+               {
+                       DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
+                       rec.Action = (short)securityAction;
+                       rec.Parent = token;
+                       // like Ref.Emit, we're using the .NET 1.x xml format
+                       rec.PermissionSet = this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
+                       this.DeclSecurity.AddRecord(rec);
+               }
+
+               internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
+               {
+                       Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
+                       foreach (CustomAttributeBuilder cab in declarativeSecurity)
+                       {
+                               int action;
+                               // check for HostProtectionAttribute without SecurityAction
+                               if (cab.ConstructorArgumentCount == 0)
+                               {
+                                       action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
+                               }
+                               else
+                               {
+                                       action = (int)cab.GetConstructorArgument(0);
+                               }
+                               List<CustomAttributeBuilder> list;
+                               if (!ordered.TryGetValue(action, out list))
+                               {
+                                       list = new List<CustomAttributeBuilder>();
+                                       ordered.Add(action, list);
+                               }
+                               list.Add(cab);
+                       }
+                       foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
+                       {
+                               DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
+                               rec.Action = (short)kv.Key;
+                               rec.Parent = token;
+                               rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
+                               this.DeclSecurity.AddRecord(rec);
+                       }
+               }
+
+               private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
+               {
+                       ByteBuffer namedArgs = new ByteBuffer(100);
+                       ByteBuffer bb = new ByteBuffer(list.Count * 100);
+                       bb.Write((byte)'.');
+                       bb.WriteCompressedInt(list.Count);
+                       foreach (CustomAttributeBuilder cab in list)
+                       {
+                               bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
+                               namedArgs.Clear();
+                               cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
+                               bb.WriteCompressedInt(namedArgs.Length);
+                               bb.Write(namedArgs);
+                       }
+                       return this.Blobs.Add(bb);
+               }
+
+               public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
+               {
+                       ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
+                       rec.Offset = manifestResources.Position;
+                       rec.Flags = (int)attribute;
+                       rec.Name = this.Strings.Add(name);
+                       rec.Implementation = 0;
+                       this.ManifestResource.AddRecord(rec);
+                       manifestResources.Write(0);     // placeholder for the length
+                       manifestResources.Write(stream);
+                       int savePosition = manifestResources.Position;
+                       manifestResources.Position = rec.Offset;
+                       manifestResources.Write(savePosition - (manifestResources.Position + 4));
+                       manifestResources.Position = savePosition;
+               }
+
+               public override Assembly Assembly
+               {
+                       get { return asm; }
+               }
+
+               internal override Type GetTypeImpl(string typeName)
+               {
+                       TypeBuilder type;
+                       fullNameToType.TryGetValue(typeName, out type);
+                       return type;
+               }
+
+               internal override void GetTypesImpl(List<Type> list)
+               {
+                       foreach (Type type in types)
+                       {
+                               if (type != moduleType)
+                               {
+                                       list.Add(type);
+                               }
+                       }
+               }
+
+               public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
+               {
+                       return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
+               }
+
+               public TypeToken GetTypeToken(string name)
+               {
+                       return new TypeToken(GetType(name, true, false).MetadataToken);
+               }
+
+               public TypeToken GetTypeToken(Type type)
+               {
+                       if (type.Module == this)
+                       {
+                               return new TypeToken(type.GetModuleBuilderToken());
+                       }
+                       else
+                       {
+                               return new TypeToken(ImportType(type));
+                       }
+               }
+
+               internal int GetTypeTokenForMemberRef(Type type)
+               {
+                       if (type.IsGenericTypeDefinition)
+                       {
+                               int token;
+                               if (!memberRefTypeTokens.TryGetValue(type, out token))
+                               {
+                                       ByteBuffer spec = new ByteBuffer(5);
+                                       Signature.WriteTypeSpec(this, spec, type);
+                                       token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
+                                       memberRefTypeTokens.Add(type, token);
+                               }
+                               return token;
+                       }
+                       else if (type.IsModulePseudoType)
+                       {
+                               return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
+                       }
+                       else
+                       {
+                               return GetTypeToken(type).Token;
+                       }
+               }
+
+               private static bool IsFromGenericTypeDefinition(MemberInfo member)
+               {
+                       Type decl = member.DeclaringType;
+                       return decl != null && decl.IsGenericTypeDefinition;
+               }
+
+               public FieldToken GetFieldToken(FieldInfo field)
+               {
+                       // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
+                       // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
+                       // simply returns the MethodDef token (if the method is from the same module).
+                       FieldBuilder fb = field as FieldBuilder;
+                       if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
+                       {
+                               return new FieldToken(fb.MetadataToken);
+                       }
+                       else
+                       {
+                               return new FieldToken(ImportMember(field));
+                       }
+               }
+
+               public MethodToken GetMethodToken(MethodInfo method)
+               {
+                       MethodBuilder mb = method as MethodBuilder;
+                       if (mb != null && mb.ModuleBuilder == this)
+                       {
+                               return new MethodToken(mb.MetadataToken);
+                       }
+                       else
+                       {
+                               return new MethodToken(ImportMember(method));
+                       }
+               }
+
+               // when we refer to a method on a generic type definition in the IL stream,
+               // we need to use a MemberRef (even if the method is in the same module)
+               internal MethodToken GetMethodTokenForIL(MethodInfo method)
+               {
+                       if (method.IsGenericMethodDefinition)
+                       {
+                               method = method.MakeGenericMethod(method.GetGenericArguments());
+                       }
+                       if (IsFromGenericTypeDefinition(method))
+                       {
+                               return new MethodToken(ImportMember(method));
+                       }
+                       else
+                       {
+                               return GetMethodToken(method);
+                       }
+               }
+
+               public MethodToken GetConstructorToken(ConstructorInfo constructor)
+               {
+                       if (constructor.Module == this && constructor.GetMethodInfo() is MethodBuilder)
+                       {
+                               return new MethodToken(constructor.MetadataToken);
+                       }
+                       else
+                       {
+                               return new MethodToken(ImportMember(constructor));
+                       }
+               }
+
+               internal int ImportMember(MethodBase member)
+               {
+                       int token;
+                       if (!importedMembers.TryGetValue(member, out token))
+                       {
+                               token = member.ImportTo(this);
+                               importedMembers.Add(member, token);
+                       }
+                       return token;
+               }
+
+               internal int ImportMember(FieldInfo member)
+               {
+                       int token;
+                       if (!importedMembers.TryGetValue(member, out token))
+                       {
+                               token = member.ImportTo(this);
+                               importedMembers.Add(member, token);
+                       }
+                       return token;
+               }
+
+               internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
+               {
+                       int token;
+                       if (!importedMemberRefs.TryGetValue(new MemberRefKey(declaringType, name, sig), out token))
+                       {
+                               MemberRefTable.Record rec = new MemberRefTable.Record();
+                               rec.Class = GetTypeTokenForMemberRef(declaringType);
+                               rec.Name = this.Strings.Add(name);
+                               ByteBuffer bb = new ByteBuffer(16);
+                               sig.WriteSig(this, bb);
+                               rec.Signature = this.Blobs.Add(bb);
+                               token = 0x0A000000 | this.MemberRef.AddRecord(rec);
+                               importedMemberRefs.Add(new MemberRefKey(declaringType, name, sig), token);
+                       }
+                       return token;
+               }
+
+               internal int ImportType(Type type)
+               {
+                       int token;
+                       if (!typeTokens.TryGetValue(type, out token))
+                       {
+                               if (type.HasElementType || (type.IsGenericType && !type.IsGenericTypeDefinition))
+                               {
+                                       ByteBuffer spec = new ByteBuffer(5);
+                                       Signature.WriteTypeSpec(this, spec, type);
+                                       token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
+                               }
+                               else
+                               {
+                                       TypeRefTable.Record rec = new TypeRefTable.Record();
+                                       if (type.IsNested)
+                                       {
+                                               rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
+                                               rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+                                               rec.TypeNameSpace = 0;
+                                       }
+                                       else
+                                       {
+                                               rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
+                                               rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+                                               string ns = type.Namespace;
+                                               rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
+                                       }
+                                       token = 0x01000000 | this.TypeRef.AddRecord(rec);
+                               }
+                               typeTokens.Add(type, token);
+                       }
+                       return token;
+               }
+
+               private int ImportAssemblyRef(Assembly asm)
+               {
+                       int token;
+                       if (!referencedAssemblies.TryGetValue(asm, out token))
+                       {
+                               // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
+                               // (if it's an AssemblyBuilder).
+                               // We set the high bit of rid in the token to make sure we emit obviously broken metadata,
+                               // if we forget to patch up the token somewhere.
+                               token = 0x23800001 + referencedAssemblies.Count;
+                               referencedAssemblies.Add(asm, token);
+                       }
+                       return token;
+               }
+
+               internal void FillAssemblyRefTable()
+               {
+                       int[] realtokens = new int[referencedAssemblies.Count];
+                       foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
+                       {
+                               realtokens[(kv.Value & 0x7FFFFF) - 1] = FindOrAddAssemblyRef(kv.Key.GetName());
+                       }
+                       // now fixup the resolution scopes in TypeRef
+                       for (int i = 0; i < this.TypeRef.records.Length; i++)
+                       {
+                               int resolutionScope = this.TypeRef.records[i].ResolutionScope;
+                               if ((resolutionScope >> 24) == AssemblyRefTable.Index)
+                               {
+                                       this.TypeRef.records[i].ResolutionScope = realtokens[(resolutionScope & 0x7FFFFF) - 1];
+                               }
+                       }
+                       // and implementation in ExportedType
+                       for (int i = 0; i < this.ExportedType.records.Length; i++)
+                       {
+                               int implementation = this.ExportedType.records[i].Implementation;
+                               if ((implementation >> 24) == AssemblyRefTable.Index)
+                               {
+                                       this.ExportedType.records[i].Implementation = realtokens[(implementation & 0x7FFFFF) - 1];
+                               }
+                       }
+               }
+
+               private int FindOrAddAssemblyRef(AssemblyName name)
+               {
+                       AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
+                       Version ver = name.Version;
+                       rec.MajorVersion = (ushort)ver.Major;
+                       rec.MinorVersion = (ushort)ver.Minor;
+                       rec.BuildNumber = (ushort)ver.Build;
+                       rec.RevisionNumber = (ushort)ver.Revision;
+                       rec.Flags = (int)(name.Flags & AssemblyNameFlags.Retargetable);
+                       byte[] publicKeyOrToken = null;
+                       if (usePublicKeyAssemblyReference)
+                       {
+                               publicKeyOrToken = name.GetPublicKey();
+                       }
+                       if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
+                       {
+                               publicKeyOrToken = name.GetPublicKeyToken();
+                       }
+                       else
+                       {
+                               const int PublicKey = 0x0001;
+                               rec.Flags |= PublicKey;
+                       }
+                       rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
+                       rec.Name = this.Strings.Add(name.Name);
+                       if (name.CultureInfo != null)
+                       {
+                               rec.Culture = this.Strings.Add(name.CultureInfo.Name);
+                       }
+                       else
+                       {
+                               rec.Culture = 0;
+                       }
+                       rec.HashValue = 0;
+                       return 0x23000000 | this.AssemblyRef.FindOrAddRecord(rec);
+               }
+
+               internal void WriteSymbolTokenMap()
+               {
+                       for (int i = 0; i < resolvedTokens.Count; i++)
+                       {
+                               int newToken = resolvedTokens[i];
+                               // The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
+                               // so we copy the type from the newToken, because our pseudo tokens don't have a type.
+                               // (see MethodToken.SymbolToken)
+                               int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
+                               SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
+                       }
+               }
+
+               internal void RegisterTokenFixup(int pseudoToken, int realToken)
+               {
+                       int index = -(pseudoToken + 1);
+                       while (resolvedTokens.Count <= index)
+                       {
+                               resolvedTokens.Add(0);
+                       }
+                       resolvedTokens[index] = realToken;
+               }
+
+               internal bool IsPseudoToken(int token)
+               {
+                       return token < 0;
+               }
+
+               internal int ResolvePseudoToken(int pseudoToken)
+               {
+                       int index = -(pseudoToken + 1);
+                       return resolvedTokens[index];
+               }
+
+               internal void FixupMethodBodyTokens()
+               {
+                       int methodToken = 0x06000001;
+                       int fieldToken = 0x04000001;
+                       int parameterToken = 0x08000001;
+                       foreach (TypeBuilder type in types)
+                       {
+                               type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
+                       }
+                       foreach (int offset in tokenFixupOffsets)
+                       {
+                               methodBodies.Position = offset;
+                               int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
+                               methodBodies.Write(ResolvePseudoToken(pseudoToken));
+                       }
+               }
+
+               private int GetHeaderLength()
+               {
+                       return
+                               4 + // Signature
+                               2 + // MajorVersion
+                               2 + // MinorVersion
+                               4 + // Reserved
+                               4 + // ImageRuntimeVersion Length
+                               StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
+                               2 + // Flags
+                               2 + // Streams
+                               4 + // #~ Offset
+                               4 + // #~ Size
+                               4 + // StringToPaddedUTF8Length("#~")
+                               4 + // #Strings Offset
+                               4 + // #Strings Size
+                               12 + // StringToPaddedUTF8Length("#Strings")
+                               4 + // #US Offset
+                               4 + // #US Size
+                               4 + // StringToPaddedUTF8Length("#US")
+                               4 + // #GUID Offset
+                               4 + // #GUID Size
+                               8 + // StringToPaddedUTF8Length("#GUID")
+                               (Blobs.IsEmpty ? 0 :
+                               (
+                               4 + // #Blob Offset
+                               4 + // #Blob Size
+                               8   // StringToPaddedUTF8Length("#Blob")
+                               ));
+               }
+
+               internal int MetadataLength
+               {
+                       get
+                       {
+                               return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
+                       }
+               }
+
+               internal void WriteMetadata(MetadataWriter mw)
+               {
+                       mw.Write(0x424A5342);                   // Signature ("BSJB")
+                       mw.Write((ushort)1);                    // MajorVersion
+                       mw.Write((ushort)1);                    // MinorVersion
+                       mw.Write(0);                                    // Reserved
+                       byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
+                       mw.Write(version.Length);               // Length
+                       mw.Write(version);
+                       mw.Write((ushort)0);                    // Flags
+                       // #Blob is the only optional heap
+                       if (Blobs.IsEmpty)
+                       {
+                               mw.Write((ushort)4);            // Streams
+                       }
+                       else
+                       {
+                               mw.Write((ushort)5);            // Streams
+                       }
+
+                       int offset = GetHeaderLength();
+
+                       // Streams
+                       mw.Write(offset);                               // Offset
+                       mw.Write(Tables.Length);                // Size
+                       mw.Write(StringToPaddedUTF8("#~"));
+                       offset += Tables.Length;
+
+                       mw.Write(offset);                               // Offset
+                       mw.Write(Strings.Length);               // Size
+                       mw.Write(StringToPaddedUTF8("#Strings"));
+                       offset += Strings.Length;
+
+                       mw.Write(offset);                               // Offset
+                       mw.Write(UserStrings.Length);   // Size
+                       mw.Write(StringToPaddedUTF8("#US"));
+                       offset += UserStrings.Length;
+
+                       mw.Write(offset);                               // Offset
+                       mw.Write(Guids.Length);                 // Size
+                       mw.Write(StringToPaddedUTF8("#GUID"));
+                       offset += Guids.Length;
+
+                       if (!Blobs.IsEmpty)
+                       {
+                               mw.Write(offset);                               // Offset
+                               mw.Write(Blobs.Length);                 // Size
+                               mw.Write(StringToPaddedUTF8("#Blob"));
+                       }
+
+                       Tables.Write(mw);
+                       Strings.Write(mw);
+                       UserStrings.Write(mw);
+                       Guids.Write(mw);
+                       if (!Blobs.IsEmpty)
+                       {
+                               Blobs.Write(mw);
+                       }
+               }
+
+               private static int StringToPaddedUTF8Length(string str)
+               {
+                       return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
+               }
+
+               private static byte[] StringToPaddedUTF8(string str)
+               {
+                       byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
+                       System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
+                       return buf;
+               }
+
+               internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
+               {
+                       manifestModule.ExportTypes(types.ToArray(), fileToken);
+               }
+
+               internal void ExportTypes(Type[] types, int fileToken)
+               {
+                       Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
+                       foreach (Type type in types)
+                       {
+                               if (!type.IsModulePseudoType && IsVisible(type))
+                               {
+                                       ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
+                                       rec.Flags = (int)type.Attributes;
+                                       rec.TypeDefId = type.MetadataToken & 0xFFFFFF;
+                                       rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+                                       string ns = type.Namespace;
+                                       rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
+                                       if (type.IsNested)
+                                       {
+                                               rec.Implementation = declaringTypes[type.DeclaringType];
+                                       }
+                                       else
+                                       {
+                                               rec.Implementation = fileToken;
+                                       }
+                                       int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
+                                       declaringTypes.Add(type, exportTypeToken);
+                               }
+                       }
+               }
+
+               private static bool IsVisible(Type type)
+               {
+                       // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
+                       return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
+               }
+
+               internal void AddConstant(int parentToken, object defaultValue)
+               {
+                       ConstantTable.Record rec = new ConstantTable.Record();
+                       rec.Parent = parentToken;
+                       ByteBuffer val = new ByteBuffer(16);
+                       if (defaultValue == null)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_CLASS;
+                               val.Write((int)0);
+                       }
+                       else if (defaultValue is bool)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
+                               val.Write((bool)defaultValue ? (byte)1 : (byte)0);
+                       }
+                       else if (defaultValue is char)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_CHAR;
+                               val.Write((char)defaultValue);
+                       }
+                       else if (defaultValue is sbyte)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_I1;
+                               val.Write((sbyte)defaultValue);
+                       }
+                       else if (defaultValue is byte)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_U1;
+                               val.Write((byte)defaultValue);
+                       }
+                       else if (defaultValue is short)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_I2;
+                               val.Write((short)defaultValue);
+                       }
+                       else if (defaultValue is ushort)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_U2;
+                               val.Write((ushort)defaultValue);
+                       }
+                       else if (defaultValue is int)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_I4;
+                               val.Write((int)defaultValue);
+                       }
+                       else if (defaultValue is uint)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_U4;
+                               val.Write((uint)defaultValue);
+                       }
+                       else if (defaultValue is long)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_I8;
+                               val.Write((long)defaultValue);
+                       }
+                       else if (defaultValue is ulong)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_U8;
+                               val.Write((ulong)defaultValue);
+                       }
+                       else if (defaultValue is float)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_R4;
+                               val.Write((float)defaultValue);
+                       }
+                       else if (defaultValue is double)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_R8;
+                               val.Write((double)defaultValue);
+                       }
+                       else if (defaultValue is string)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_STRING;
+                               foreach (char c in (string)defaultValue)
+                               {
+                                       val.Write(c);
+                               }
+                       }
+                       else if (defaultValue is DateTime)
+                       {
+                               rec.Type = Signature.ELEMENT_TYPE_I8;
+                               val.Write(((DateTime)defaultValue).Ticks);
+                       }
+                       else
+                       {
+                               throw new ArgumentException();
+                       }
+                       rec.Value = this.Blobs.Add(val);
+                       this.Constant.AddRecord(rec);
+               }
+
+               ModuleBuilder ITypeOwner.ModuleBuilder
+               {
+                       get { return this; }
+               }
+
+               public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       if (genericTypeArguments != null || genericMethodArguments != null)
+                       {
+                               throw new NotImplementedException();
+                       }
+                       return types[(metadataToken & 0xFFFFFF) - 1];
+               }
+
+               public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       if (genericTypeArguments != null || genericMethodArguments != null)
+                       {
+                               throw new NotImplementedException();
+                       }
+                       // this method is inefficient, but since it isn't used we don't care
+                       if ((metadataToken >> 24) == MemberRefTable.Index)
+                       {
+                               foreach (KeyValuePair<MemberInfo, int> kv in importedMembers)
+                               {
+                                       if (kv.Value == metadataToken)
+                                       {
+                                               return (MethodBase)kv.Key;
+                                       }
+                               }
+                       }
+                       // HACK if we're given a SymbolToken, we need to convert back
+                       if ((metadataToken & 0xFF000000) == 0x06000000)
+                       {
+                               metadataToken = -(metadataToken & 0x00FFFFFF);
+                       }
+                       foreach (Type type in types)
+                       {
+                               MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
+                               if (method != null)
+                               {
+                                       return method;
+                               }
+                       }
+                       return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
+               }
+
+               public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public override string ResolveString(int metadataToken)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public override string FullyQualifiedName
+               {
+                       get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
+               }
+
+               public override string Name
+               {
+                       get { return fileName; }
+               }
+
+               public override Guid ModuleVersionId
+               {
+                       get { return mvid; }
+               }
+
+               public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public override string ScopeName
+               {
+                       get { return moduleName; }
+               }
+
+               public ISymbolWriter GetSymWriter()
+               {
+                       return symbolWriter;
+               }
+
+               public void DefineUnmanagedResource(string resourceFileName)
+               {
+                       // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
+                       // also setting the Resource Directory entry.
+                       unmanagedResources = new ResourceSection();
+                       unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
+               }
+
+               public bool IsTransient()
+               {
+                       return false;
+               }
+
+               public void SetUserEntryPoint(MethodInfo entryPoint)
+               {
+                       int token = entryPoint.MetadataToken;
+                       if (token < 0)
+                       {
+                               token = -token | 0x06000000;
+                       }
+                       if (symbolWriter != null)
+                       {
+                               symbolWriter.SetUserEntryPoint(new SymbolToken(token));
+                       }
+               }
+
+               public StringToken GetStringConstant(string str)
+               {
+                       return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
+               }
+
+               public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
+               {
+                       return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
+               }
+
+               public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
+               {
+                       return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
+               }
+
+               public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
+               }
+
+               public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
+               }
+
+               internal override Type GetModuleType()
+               {
+                       return moduleType;
+               }
+
+               internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+               {
+                       return Blobs.GetBlob(blobIndex);
+               }
+
+               internal int GetSignatureBlobIndex(Signature sig)
+               {
+                       ByteBuffer bb = new ByteBuffer(16);
+                       sig.WriteSig(this, bb);
+                       return this.Blobs.Add(bb);
+               }
+
+               // non-standard API
+               public long __ImageBase
+               {
+                       get { return imageBaseAddress; }
+                       set { imageBaseAddress = value; }
+               }
+
+               public override int MDStreamVersion
+               {
+                       get { return asm.mdStreamVersion; }
+               }
+
+               private int AddTypeRefByName(int resolutionScope, string ns, string name)
+               {
+                       TypeRefTable.Record rec = new TypeRefTable.Record();
+                       rec.ResolutionScope = resolutionScope;
+                       rec.TypeName = this.Strings.Add(name);
+                       rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
+                       return 0x01000000 | this.TypeRef.AddRecord(rec);
+               }
+
+               public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+               {
+                       PopulatePropertyAndEventTables();
+                       IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
+                       if (attributes.Count > 0)
+                       {
+                               int mscorlib = ImportAssemblyRef(universe.Mscorlib);
+                               int[] placeholderTokens = new int[4];
+                               string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
+                               foreach (CustomAttributeData cad in attributes)
+                               {
+                                       int index;
+                                       if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
+                                       {
+                                               if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
+                                               {
+                                                       index = 3;
+                                               }
+                                               else
+                                               {
+                                                       index = 2;
+                                               }
+                                       }
+                                       else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
+                                       {
+                                               index = 1;
+                                       }
+                                       else
+                                       {
+                                               index = 0;
+                                       }
+                                       if (placeholderTokens[index] == 0)
+                                       {
+                                               // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
+                                               placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
+                                       }
+                                       SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
+                               }
+                       }
+                       FillAssemblyRefTable();
+                       ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0);
+               }
+
+               public void __AddAssemblyReference(AssemblyName assemblyName)
+               {
+                       if (referencedAssemblyNames == null)
+                       {
+                               referencedAssemblyNames = new List<AssemblyName>();
+                       }
+                       FindOrAddAssemblyRef(assemblyName);
+                       referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
+               }
+
+               public override AssemblyName[] __GetReferencedAssemblies()
+               {
+                       List<AssemblyName> list = new List<AssemblyName>();
+                       if (referencedAssemblyNames != null)
+                       {
+                               foreach (AssemblyName name in referencedAssemblyNames)
+                               {
+                                       if (!list.Contains(name))
+                                       {
+                                               list.Add(name);
+                                       }
+                               }
+                       }
+                       foreach (Assembly asm in referencedAssemblies.Keys)
+                       {
+                               AssemblyName name = asm.GetName();
+                               if (!list.Contains(name))
+                               {
+                                       list.Add(name);
+                               }
+                       }
+                       return list.ToArray();
+               }
+       }
+
+       class ArrayMethod : MethodInfo
+       {
+               private readonly Module module;
+               private readonly Type arrayClass;
+               private readonly string methodName;
+               private readonly CallingConventions callingConvention;
+               private readonly Type returnType;
+               protected readonly Type[] parameterTypes;
+               private MethodSignature methodSignature;
+
+               internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       this.module = module;
+                       this.arrayClass = arrayClass;
+                       this.methodName = methodName;
+                       this.callingConvention = callingConvention;
+                       this.returnType = returnType ?? module.universe.System_Void;
+                       this.parameterTypes = Util.Copy(parameterTypes);
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override ParameterInfo[] GetParameters()
+               {
+                       throw new NotSupportedException();
+               }
+
+               internal override int ImportTo(ModuleBuilder module)
+               {
+                       return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public override CallingConventions CallingConvention
+               {
+                       get { return callingConvention; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return arrayClass; }
+               }
+
+               internal override MethodSignature MethodSignature
+               {
+                       get
+                       {
+                               if (methodSignature == null)
+                               {
+                                       methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, null, callingConvention, 0);
+                               }
+                               return methodSignature;
+                       }
+               }
+
+               public override Module Module
+               {
+                       // like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
+                       get { return module; }
+               }
+
+               public override string Name
+               {
+                       get { return methodName; }
+               }
+
+               internal override int ParameterCount
+               {
+                       get { return parameterTypes.Length; }
+               }
+
+               public override ParameterInfo ReturnParameter
+               {
+                       get { throw new NotImplementedException(); }
+               }
+
+               public override Type ReturnType
+               {
+                       get { return returnType; }
+               }
+
+               internal override bool HasThis
+               {
+                       get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/OpCode.cs b/mcs/class/IKVM.Reflection/Emit/OpCode.cs
new file mode 100644 (file)
index 0000000..1d75a0a
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+  Copyright (C) 2008, 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Diagnostics;
+
+namespace IKVM.Reflection.Emit
+{
+       public struct OpCode
+       {
+               private const int ValueCount = 1024;
+               private const int OperandTypeCount = 19;
+               private const int FlowControlCount = 9;
+               private const int StackDiffCount = 5;
+               private const int OpCodeTypeCount = 6;
+               private const int StackBehaviourPopCount = 20;
+               private const int StackBehaviourPushCount = 9;
+               private static readonly StackBehaviour[] pop = {
+                       StackBehaviour.Pop0,
+                       StackBehaviour.Pop1,
+                       StackBehaviour.Pop1_pop1,
+                       StackBehaviour.Popi,
+                       StackBehaviour.Popi_pop1,
+                       StackBehaviour.Popi_popi,
+                       StackBehaviour.Popi_popi8,
+                       StackBehaviour.Popi_popi_popi,
+                       StackBehaviour.Popi_popr4,
+                       StackBehaviour.Popi_popr8,
+                       StackBehaviour.Popref,
+                       StackBehaviour.Popref_pop1,
+                       StackBehaviour.Popref_popi,
+                       StackBehaviour.Popref_popi_popi,
+                       StackBehaviour.Popref_popi_popi8,
+                       StackBehaviour.Popref_popi_popr4,
+                       StackBehaviour.Popref_popi_popr8,
+                       StackBehaviour.Popref_popi_popref,
+                       StackBehaviour.Varpop,
+                       StackBehaviour.Popref_popi_pop1
+               };
+               private static readonly StackBehaviour[] push = {
+                       StackBehaviour.Push0,
+                       StackBehaviour.Push1,
+                       StackBehaviour.Push1_push1,
+                       StackBehaviour.Pushi,
+                       StackBehaviour.Pushi8,
+                       StackBehaviour.Pushr4,
+                       StackBehaviour.Pushr8,
+                       StackBehaviour.Pushref,
+                       StackBehaviour.Varpush
+               };
+               private readonly int value;
+
+               internal OpCode(int value)
+               {
+                       this.value = value;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return this == obj as OpCode?;
+               }
+
+               public override int GetHashCode()
+               {
+                       return value;
+               }
+
+               public bool Equals(OpCode other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(OpCode a, OpCode b)
+               {
+                       return a.value == b.value;
+               }
+
+               public static bool operator !=(OpCode a, OpCode b)
+               {
+                       return !(a == b);
+               }
+
+               public short Value
+               {
+                       get { return (short)(value >> 22); }
+               }
+
+               public int Size
+               {
+                       get { return value < 0 ? 2 : 1; }
+               }
+
+#if !GENERATOR
+               public string Name
+               {
+                       get { return OpCodes.GetName(this.Value); }
+               }
+#endif
+
+               public OperandType OperandType
+               {
+                       get { return (OperandType)((value & 0x3FFFFF) % OperandTypeCount); }
+               }
+
+               public FlowControl FlowControl
+               {
+                       get { return (FlowControl)(((value & 0x3FFFFF) / OperandTypeCount) % FlowControlCount); }
+               }
+
+               internal int StackDiff
+               {
+                       get { return ((((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount)) % StackDiffCount) - 3); }
+               }
+
+               public OpCodeType OpCodeType
+               {
+                       get { return (OpCodeType)(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount)) % OpCodeTypeCount); }
+               }
+
+               public StackBehaviour StackBehaviourPop
+               {
+                       get { return pop[(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount * OpCodeTypeCount)) % StackBehaviourPopCount)]; }
+               }
+
+               public StackBehaviour StackBehaviourPush
+               {
+                       get { return push[(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount * OpCodeTypeCount * StackBehaviourPopCount)) % StackBehaviourPushCount)]; }
+               }
+
+#if GENERATOR
+               static void Main(string[] args)
+               {
+                       Debug.Assert(pop.Length == StackBehaviourPopCount);
+                       Debug.Assert(push.Length == StackBehaviourPushCount);
+                       CheckEnumRange(typeof(FlowControl), FlowControlCount);
+                       CheckEnumRange(typeof(OpCodeType), OpCodeTypeCount);
+                       CheckEnumRange(typeof(OperandType), OperandTypeCount);
+                       foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+                       {
+                               System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null);
+                               IKVM.Reflection.Emit.OpCode opc2 = new IKVM.Reflection.Emit.OpCode(Pack(opc1));
+                               Debug.Assert(opc1.Value == opc2.Value);
+                               Debug.Assert(opc1.Size == opc2.Size);
+                               Debug.Assert((int)opc1.FlowControl == (int)opc2.FlowControl);
+                               Debug.Assert((int)opc1.OpCodeType == (int)opc2.OpCodeType);
+                               Debug.Assert((int)opc1.OperandType == (int)opc2.OperandType);
+                               Debug.Assert((int)opc1.StackBehaviourPop == (int)opc2.StackBehaviourPop);
+                               Debug.Assert((int)opc1.StackBehaviourPush == (int)opc2.StackBehaviourPush);
+                               Console.WriteLine("\t\tpublic static readonly OpCode {0} = new OpCode({1});", field.Name, Pack(opc1));
+                       }
+                       Console.WriteLine();
+                       Console.WriteLine("\t\tinternal static string GetName(int value)");
+                       Console.WriteLine("\t\t{");
+                       Console.WriteLine("\t\t\tswitch (value)");
+                       Console.WriteLine("\t\t\t{");
+                       foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+                       {
+                               System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null);
+                               Console.WriteLine("\t\t\t\tcase {0}:", opc1.Value);
+                               Console.WriteLine("\t\t\t\t\treturn \"{0}\";", opc1.Name);
+                       }
+                       Console.WriteLine("\t\t\t}");
+                       Console.WriteLine("\t\t\tthrow new ArgumentOutOfRangeException();");
+                       Console.WriteLine("\t\t}");
+                       Console.WriteLine();
+                       Console.WriteLine("\t\tpublic static bool TakesSingleByteArgument(OpCode inst)");
+                       Console.WriteLine("\t\t{");
+                       Console.WriteLine("\t\t\tswitch (inst.Value)");
+                       Console.WriteLine("\t\t\t{");
+                       foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+                       {
+                               System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null);
+                               if (System.Reflection.Emit.OpCodes.TakesSingleByteArgument(opc1))
+                               {
+                                       Console.WriteLine("\t\t\t\tcase {0}:", opc1.Value);
+                               }
+                       }
+                       Console.WriteLine("\t\t\t\t\treturn true;");
+                       Console.WriteLine("\t\t\t\tdefault:");
+                       Console.WriteLine("\t\t\t\t\treturn false;");
+                       Console.WriteLine("\t\t\t}");
+                       Console.WriteLine("\t\t}");
+               }
+
+               private static void CheckEnumRange(System.Type type, int count)
+               {
+                       foreach (var field in type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+                       {
+                               int value = (int)field.GetValue(null);
+                               Debug.Assert(value >= 0 && value < count);
+                       }
+               }
+
+               static int Pack(System.Reflection.Emit.OpCode opcode)
+               {
+                       int value = 0;
+                       value *= StackBehaviourPushCount;
+                       value += Map(push, opcode.StackBehaviourPush);
+                       value *= StackBehaviourPopCount;
+                       value += Map(pop, opcode.StackBehaviourPop);
+                       value *= OpCodeTypeCount;
+                       value += (int)opcode.OpCodeType;
+                       value *= StackDiffCount;
+                       value += 3 + GetStackDiff(opcode.StackBehaviourPush) + GetStackDiff(opcode.StackBehaviourPop);
+                       value *= FlowControlCount;
+                       value += (int)opcode.FlowControl;
+                       value *= OperandTypeCount;
+                       value += (int)opcode.OperandType;
+                       return (opcode.Value << 22) | value;
+               }
+
+               private static int Map(StackBehaviour[] array, System.Reflection.Emit.StackBehaviour stackBehaviour)
+               {
+                       for (int i = 0; i < array.Length; i++)
+                       {
+                               if ((int)array[i] == (int)stackBehaviour)
+                               {
+                                       return i;
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               static int GetStackDiff(System.Reflection.Emit.StackBehaviour sb)
+               {
+                       switch (sb)
+                       {
+                               case System.Reflection.Emit.StackBehaviour.Pop0:
+                               case System.Reflection.Emit.StackBehaviour.Push0:
+                               case System.Reflection.Emit.StackBehaviour.Varpop:
+                               case System.Reflection.Emit.StackBehaviour.Varpush:
+                                       return 0;
+                               case System.Reflection.Emit.StackBehaviour.Pop1:
+                               case System.Reflection.Emit.StackBehaviour.Popi:
+                               case System.Reflection.Emit.StackBehaviour.Popref:
+                                       return -1;
+                               case System.Reflection.Emit.StackBehaviour.Pop1_pop1:
+                               case System.Reflection.Emit.StackBehaviour.Popi_pop1:
+                               case System.Reflection.Emit.StackBehaviour.Popi_popi:
+                               case System.Reflection.Emit.StackBehaviour.Popi_popi8:
+                               case System.Reflection.Emit.StackBehaviour.Popi_popr4:
+                               case System.Reflection.Emit.StackBehaviour.Popi_popr8:
+                               case System.Reflection.Emit.StackBehaviour.Popref_pop1:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi:
+                                       return -2;
+                               case System.Reflection.Emit.StackBehaviour.Popi_popi_popi:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi_pop1:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi_popi:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi_popi8:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi_popr4:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi_popr8:
+                               case System.Reflection.Emit.StackBehaviour.Popref_popi_popref:
+                                       return -3;
+                               case System.Reflection.Emit.StackBehaviour.Push1:
+                               case System.Reflection.Emit.StackBehaviour.Pushi:
+                               case System.Reflection.Emit.StackBehaviour.Pushi8:
+                               case System.Reflection.Emit.StackBehaviour.Pushr4:
+                               case System.Reflection.Emit.StackBehaviour.Pushr8:
+                               case System.Reflection.Emit.StackBehaviour.Pushref:
+                                       return 1;
+                               case System.Reflection.Emit.StackBehaviour.Push1_push1:
+                                       return 2;
+                       }
+                       throw new InvalidOperationException();
+               }
+#endif // GENERATOR
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/OpCodes.cs b/mcs/class/IKVM.Reflection/Emit/OpCodes.cs
new file mode 100644 (file)
index 0000000..7d4bcb0
--- /dev/null
@@ -0,0 +1,749 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection.Emit
+{
+       public class OpCodes
+       {
+               public static readonly OpCode Nop = new OpCode(4888);
+               public static readonly OpCode Break = new OpCode(4199116);
+               public static readonly OpCode Ldarg_0 = new OpCode(8492847);
+               public static readonly OpCode Ldarg_1 = new OpCode(12687151);
+               public static readonly OpCode Ldarg_2 = new OpCode(16881455);
+               public static readonly OpCode Ldarg_3 = new OpCode(21075759);
+               public static readonly OpCode Ldloc_0 = new OpCode(25270063);
+               public static readonly OpCode Ldloc_1 = new OpCode(29464367);
+               public static readonly OpCode Ldloc_2 = new OpCode(33658671);
+               public static readonly OpCode Ldloc_3 = new OpCode(37852975);
+               public static readonly OpCode Stloc_0 = new OpCode(41949467);
+               public static readonly OpCode Stloc_1 = new OpCode(46143771);
+               public static readonly OpCode Stloc_2 = new OpCode(50338075);
+               public static readonly OpCode Stloc_3 = new OpCode(54532379);
+               public static readonly OpCode Ldarg_S = new OpCode(58824508);
+               public static readonly OpCode Ldarga_S = new OpCode(63224012);
+               public static readonly OpCode Starg_S = new OpCode(67115304);
+               public static readonly OpCode Ldloc_S = new OpCode(71407420);
+               public static readonly OpCode Ldloca_S = new OpCode(75806924);
+               public static readonly OpCode Stloc_S = new OpCode(79698216);
+               public static readonly OpCode Ldnull = new OpCode(84609339);
+               public static readonly OpCode Ldc_I4_M1 = new OpCode(88389823);
+               public static readonly OpCode Ldc_I4_0 = new OpCode(92584127);
+               public static readonly OpCode Ldc_I4_1 = new OpCode(96778431);
+               public static readonly OpCode Ldc_I4_2 = new OpCode(100972735);
+               public static readonly OpCode Ldc_I4_3 = new OpCode(105167039);
+               public static readonly OpCode Ldc_I4_4 = new OpCode(109361343);
+               public static readonly OpCode Ldc_I4_5 = new OpCode(113555647);
+               public static readonly OpCode Ldc_I4_6 = new OpCode(117749951);
+               public static readonly OpCode Ldc_I4_7 = new OpCode(121944255);
+               public static readonly OpCode Ldc_I4_8 = new OpCode(126138559);
+               public static readonly OpCode Ldc_I4_S = new OpCode(130332874);
+               public static readonly OpCode Ldc_I4 = new OpCode(134530584);
+               public static readonly OpCode Ldc_I8 = new OpCode(138827489);
+               public static readonly OpCode Ldc_R4 = new OpCode(143124407);
+               public static readonly OpCode Ldc_R8 = new OpCode(147421301);
+               public static readonly OpCode Dup = new OpCode(155404637);
+               public static readonly OpCode Pop = new OpCode(159393399);
+               public static readonly OpCode Jmp = new OpCode(163582686);
+               public static readonly OpCode Call = new OpCode(168690130);
+               public static readonly OpCode Calli = new OpCode(172884439);
+               public static readonly OpCode Ret = new OpCode(176258034);
+               public static readonly OpCode Br_S = new OpCode(180356455);
+               public static readonly OpCode Brfalse_S = new OpCode(184566035);
+               public static readonly OpCode Brtrue_S = new OpCode(188760339);
+               public static readonly OpCode Beq_S = new OpCode(192949342);
+               public static readonly OpCode Bge_S = new OpCode(197143646);
+               public static readonly OpCode Bgt_S = new OpCode(201337950);
+               public static readonly OpCode Ble_S = new OpCode(205532254);
+               public static readonly OpCode Blt_S = new OpCode(209726558);
+               public static readonly OpCode Bne_Un_S = new OpCode(213920862);
+               public static readonly OpCode Bge_Un_S = new OpCode(218115166);
+               public static readonly OpCode Bgt_Un_S = new OpCode(222309470);
+               public static readonly OpCode Ble_Un_S = new OpCode(226503774);
+               public static readonly OpCode Blt_Un_S = new OpCode(230698078);
+               public static readonly OpCode Br = new OpCode(234885812);
+               public static readonly OpCode Brfalse = new OpCode(239095392);
+               public static readonly OpCode Brtrue = new OpCode(243289696);
+               public static readonly OpCode Beq = new OpCode(247475279);
+               public static readonly OpCode Bge = new OpCode(251669583);
+               public static readonly OpCode Bgt = new OpCode(255863887);
+               public static readonly OpCode Ble = new OpCode(260058191);
+               public static readonly OpCode Blt = new OpCode(264252495);
+               public static readonly OpCode Bne_Un = new OpCode(268446799);
+               public static readonly OpCode Bge_Un = new OpCode(272641103);
+               public static readonly OpCode Bgt_Un = new OpCode(276835407);
+               public static readonly OpCode Ble_Un = new OpCode(281029711);
+               public static readonly OpCode Blt_Un = new OpCode(285224015);
+               public static readonly OpCode Switch = new OpCode(289427051);
+               public static readonly OpCode Ldind_I1 = new OpCode(293929358);
+               public static readonly OpCode Ldind_U1 = new OpCode(298123662);
+               public static readonly OpCode Ldind_I2 = new OpCode(302317966);
+               public static readonly OpCode Ldind_U2 = new OpCode(306512270);
+               public static readonly OpCode Ldind_I4 = new OpCode(310706574);
+               public static readonly OpCode Ldind_U4 = new OpCode(314900878);
+               public static readonly OpCode Ldind_I8 = new OpCode(319197782);
+               public static readonly OpCode Ldind_I = new OpCode(323289486);
+               public static readonly OpCode Ldind_R4 = new OpCode(327688990);
+               public static readonly OpCode Ldind_R8 = new OpCode(331985894);
+               public static readonly OpCode Ldind_Ref = new OpCode(336282798);
+               public static readonly OpCode Stind_Ref = new OpCode(339768820);
+               public static readonly OpCode Stind_I1 = new OpCode(343963124);
+               public static readonly OpCode Stind_I2 = new OpCode(348157428);
+               public static readonly OpCode Stind_I4 = new OpCode(352351732);
+               public static readonly OpCode Stind_I8 = new OpCode(356551166);
+               public static readonly OpCode Stind_R4 = new OpCode(360755730);
+               public static readonly OpCode Stind_R8 = new OpCode(364955164);
+               public static readonly OpCode Add = new OpCode(369216329);
+               public static readonly OpCode Sub = new OpCode(373410633);
+               public static readonly OpCode Mul = new OpCode(377604937);
+               public static readonly OpCode Div = new OpCode(381799241);
+               public static readonly OpCode Div_Un = new OpCode(385993545);
+               public static readonly OpCode Rem = new OpCode(390187849);
+               public static readonly OpCode Rem_Un = new OpCode(394382153);
+               public static readonly OpCode And = new OpCode(398576457);
+               public static readonly OpCode Or = new OpCode(402770761);
+               public static readonly OpCode Xor = new OpCode(406965065);
+               public static readonly OpCode Shl = new OpCode(411159369);
+               public static readonly OpCode Shr = new OpCode(415353673);
+               public static readonly OpCode Shr_Un = new OpCode(419547977);
+               public static readonly OpCode Neg = new OpCode(423737322);
+               public static readonly OpCode Not = new OpCode(427931626);
+               public static readonly OpCode Conv_I1 = new OpCode(432331130);
+               public static readonly OpCode Conv_I2 = new OpCode(436525434);
+               public static readonly OpCode Conv_I4 = new OpCode(440719738);
+               public static readonly OpCode Conv_I8 = new OpCode(445016642);
+               public static readonly OpCode Conv_R4 = new OpCode(449313546);
+               public static readonly OpCode Conv_R8 = new OpCode(453610450);
+               public static readonly OpCode Conv_U4 = new OpCode(457496954);
+               public static readonly OpCode Conv_U8 = new OpCode(461793858);
+               public static readonly OpCode Callvirt = new OpCode(466484004);
+               public static readonly OpCode Cpobj = new OpCode(469790542);
+               public static readonly OpCode Ldobj = new OpCode(474077528);
+               public static readonly OpCode Ldstr = new OpCode(478872210);
+               public static readonly OpCode Newobj = new OpCode(483158791);
+               public static readonly OpCode Castclass = new OpCode(487311950);
+               public static readonly OpCode Isinst = new OpCode(491095854);
+               public static readonly OpCode Conv_R_Un = new OpCode(495553490);
+               public static readonly OpCode Unbox = new OpCode(507874780);
+               public static readonly OpCode Throw = new OpCode(511759452);
+               public static readonly OpCode Ldfld = new OpCode(516056466);
+               public static readonly OpCode Ldflda = new OpCode(520455970);
+               public static readonly OpCode Stfld = new OpCode(524347262);
+               public static readonly OpCode Ldsfld = new OpCode(528588249);
+               public static readonly OpCode Ldsflda = new OpCode(532987753);
+               public static readonly OpCode Stsfld = new OpCode(536879045);
+               public static readonly OpCode Stobj = new OpCode(541090290);
+               public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(545577338);
+               public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(549771642);
+               public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(553965946);
+               public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(558262850);
+               public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(562354554);
+               public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(566548858);
+               public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(570743162);
+               public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(575040066);
+               public static readonly OpCode Conv_Ovf_I_Un = new OpCode(579131770);
+               public static readonly OpCode Conv_Ovf_U_Un = new OpCode(583326074);
+               public static readonly OpCode Box = new OpCode(587930786);
+               public static readonly OpCode Newarr = new OpCode(592133640);
+               public static readonly OpCode Ldlen = new OpCode(595953446);
+               public static readonly OpCode Ldelema = new OpCode(600157847);
+               public static readonly OpCode Ldelem_I1 = new OpCode(604352143);
+               public static readonly OpCode Ldelem_U1 = new OpCode(608546447);
+               public static readonly OpCode Ldelem_I2 = new OpCode(612740751);
+               public static readonly OpCode Ldelem_U2 = new OpCode(616935055);
+               public static readonly OpCode Ldelem_I4 = new OpCode(621129359);
+               public static readonly OpCode Ldelem_U4 = new OpCode(625323663);
+               public static readonly OpCode Ldelem_I8 = new OpCode(629620567);
+               public static readonly OpCode Ldelem_I = new OpCode(633712271);
+               public static readonly OpCode Ldelem_R4 = new OpCode(638111775);
+               public static readonly OpCode Ldelem_R8 = new OpCode(642408679);
+               public static readonly OpCode Ldelem_Ref = new OpCode(646705583);
+               public static readonly OpCode Stelem_I = new OpCode(650186475);
+               public static readonly OpCode Stelem_I1 = new OpCode(654380779);
+               public static readonly OpCode Stelem_I2 = new OpCode(658575083);
+               public static readonly OpCode Stelem_I4 = new OpCode(662769387);
+               public static readonly OpCode Stelem_I8 = new OpCode(666968821);
+               public static readonly OpCode Stelem_R4 = new OpCode(671168255);
+               public static readonly OpCode Stelem_R8 = new OpCode(675367689);
+               public static readonly OpCode Stelem_Ref = new OpCode(679567123);
+               public static readonly OpCode Ldelem = new OpCode(683838727);
+               public static readonly OpCode Stelem = new OpCode(687965999);
+               public static readonly OpCode Unbox_Any = new OpCode(692217246);
+               public static readonly OpCode Conv_Ovf_I1 = new OpCode(751098234);
+               public static readonly OpCode Conv_Ovf_U1 = new OpCode(755292538);
+               public static readonly OpCode Conv_Ovf_I2 = new OpCode(759486842);
+               public static readonly OpCode Conv_Ovf_U2 = new OpCode(763681146);
+               public static readonly OpCode Conv_Ovf_I4 = new OpCode(767875450);
+               public static readonly OpCode Conv_Ovf_U4 = new OpCode(772069754);
+               public static readonly OpCode Conv_Ovf_I8 = new OpCode(776366658);
+               public static readonly OpCode Conv_Ovf_U8 = new OpCode(780560962);
+               public static readonly OpCode Refanyval = new OpCode(814012802);
+               public static readonly OpCode Ckfinite = new OpCode(818514898);
+               public static readonly OpCode Mkrefany = new OpCode(830595078);
+               public static readonly OpCode Ldtoken = new OpCode(872728098);
+               public static readonly OpCode Conv_U2 = new OpCode(876927354);
+               public static readonly OpCode Conv_U1 = new OpCode(881121658);
+               public static readonly OpCode Conv_I = new OpCode(885315962);
+               public static readonly OpCode Conv_Ovf_I = new OpCode(889510266);
+               public static readonly OpCode Conv_Ovf_U = new OpCode(893704570);
+               public static readonly OpCode Add_Ovf = new OpCode(897698633);
+               public static readonly OpCode Add_Ovf_Un = new OpCode(901892937);
+               public static readonly OpCode Mul_Ovf = new OpCode(906087241);
+               public static readonly OpCode Mul_Ovf_Un = new OpCode(910281545);
+               public static readonly OpCode Sub_Ovf = new OpCode(914475849);
+               public static readonly OpCode Sub_Ovf_Un = new OpCode(918670153);
+               public static readonly OpCode Endfinally = new OpCode(922751806);
+               public static readonly OpCode Leave = new OpCode(926945972);
+               public static readonly OpCode Leave_S = new OpCode(931140291);
+               public static readonly OpCode Stind_I = new OpCode(935359988);
+               public static readonly OpCode Conv_U = new OpCode(939841914);
+               public static readonly OpCode Prefix7 = new OpCode(1040189696);
+               public static readonly OpCode Prefix6 = new OpCode(1044384000);
+               public static readonly OpCode Prefix5 = new OpCode(1048578304);
+               public static readonly OpCode Prefix4 = new OpCode(1052772608);
+               public static readonly OpCode Prefix3 = new OpCode(1056966912);
+               public static readonly OpCode Prefix2 = new OpCode(1061161216);
+               public static readonly OpCode Prefix1 = new OpCode(1065355520);
+               public static readonly OpCode Prefixref = new OpCode(1069549824);
+               public static readonly OpCode Arglist = new OpCode(-2147170789);
+               public static readonly OpCode Ceq = new OpCode(-2142966567);
+               public static readonly OpCode Cgt = new OpCode(-2138772263);
+               public static readonly OpCode Cgt_Un = new OpCode(-2134577959);
+               public static readonly OpCode Clt = new OpCode(-2130383655);
+               public static readonly OpCode Clt_Un = new OpCode(-2126189351);
+               public static readonly OpCode Ldftn = new OpCode(-2122004966);
+               public static readonly OpCode Ldvirtftn = new OpCode(-2117759533);
+               public static readonly OpCode Ldarg = new OpCode(-2109627244);
+               public static readonly OpCode Ldarga = new OpCode(-2105227740);
+               public static readonly OpCode Starg = new OpCode(-2101336448);
+               public static readonly OpCode Ldloc = new OpCode(-2097044332);
+               public static readonly OpCode Ldloca = new OpCode(-2092644828);
+               public static readonly OpCode Stloc = new OpCode(-2088753536);
+               public static readonly OpCode Localloc = new OpCode(-2084241010);
+               public static readonly OpCode Endfilter = new OpCode(-2076160335);
+               public static readonly OpCode Unaligned = new OpCode(-2071982151);
+               public static readonly OpCode Volatile = new OpCode(-2067787858);
+               public static readonly OpCode Tailcall = new OpCode(-2063593554);
+               public static readonly OpCode Initobj = new OpCode(-2059384859);
+               public static readonly OpCode Constrained = new OpCode(-2055204938);
+               public static readonly OpCode Cpblk = new OpCode(-2050974371);
+               public static readonly OpCode Initblk = new OpCode(-2046780067);
+               public static readonly OpCode Rethrow = new OpCode(-2038428509);
+               public static readonly OpCode Sizeof = new OpCode(-2029730269);
+               public static readonly OpCode Refanytype = new OpCode(-2025531014);
+               public static readonly OpCode Readonly = new OpCode(-2021650514);
+
+               internal static string GetName(int value)
+               {
+                       switch (value)
+                       {
+                               case 0:
+                                       return "nop";
+                               case 1:
+                                       return "break";
+                               case 2:
+                                       return "ldarg.0";
+                               case 3:
+                                       return "ldarg.1";
+                               case 4:
+                                       return "ldarg.2";
+                               case 5:
+                                       return "ldarg.3";
+                               case 6:
+                                       return "ldloc.0";
+                               case 7:
+                                       return "ldloc.1";
+                               case 8:
+                                       return "ldloc.2";
+                               case 9:
+                                       return "ldloc.3";
+                               case 10:
+                                       return "stloc.0";
+                               case 11:
+                                       return "stloc.1";
+                               case 12:
+                                       return "stloc.2";
+                               case 13:
+                                       return "stloc.3";
+                               case 14:
+                                       return "ldarg.s";
+                               case 15:
+                                       return "ldarga.s";
+                               case 16:
+                                       return "starg.s";
+                               case 17:
+                                       return "ldloc.s";
+                               case 18:
+                                       return "ldloca.s";
+                               case 19:
+                                       return "stloc.s";
+                               case 20:
+                                       return "ldnull";
+                               case 21:
+                                       return "ldc.i4.m1";
+                               case 22:
+                                       return "ldc.i4.0";
+                               case 23:
+                                       return "ldc.i4.1";
+                               case 24:
+                                       return "ldc.i4.2";
+                               case 25:
+                                       return "ldc.i4.3";
+                               case 26:
+                                       return "ldc.i4.4";
+                               case 27:
+                                       return "ldc.i4.5";
+                               case 28:
+                                       return "ldc.i4.6";
+                               case 29:
+                                       return "ldc.i4.7";
+                               case 30:
+                                       return "ldc.i4.8";
+                               case 31:
+                                       return "ldc.i4.s";
+                               case 32:
+                                       return "ldc.i4";
+                               case 33:
+                                       return "ldc.i8";
+                               case 34:
+                                       return "ldc.r4";
+                               case 35:
+                                       return "ldc.r8";
+                               case 37:
+                                       return "dup";
+                               case 38:
+                                       return "pop";
+                               case 39:
+                                       return "jmp";
+                               case 40:
+                                       return "call";
+                               case 41:
+                                       return "calli";
+                               case 42:
+                                       return "ret";
+                               case 43:
+                                       return "br.s";
+                               case 44:
+                                       return "brfalse.s";
+                               case 45:
+                                       return "brtrue.s";
+                               case 46:
+                                       return "beq.s";
+                               case 47:
+                                       return "bge.s";
+                               case 48:
+                                       return "bgt.s";
+                               case 49:
+                                       return "ble.s";
+                               case 50:
+                                       return "blt.s";
+                               case 51:
+                                       return "bne.un.s";
+                               case 52:
+                                       return "bge.un.s";
+                               case 53:
+                                       return "bgt.un.s";
+                               case 54:
+                                       return "ble.un.s";
+                               case 55:
+                                       return "blt.un.s";
+                               case 56:
+                                       return "br";
+                               case 57:
+                                       return "brfalse";
+                               case 58:
+                                       return "brtrue";
+                               case 59:
+                                       return "beq";
+                               case 60:
+                                       return "bge";
+                               case 61:
+                                       return "bgt";
+                               case 62:
+                                       return "ble";
+                               case 63:
+                                       return "blt";
+                               case 64:
+                                       return "bne.un";
+                               case 65:
+                                       return "bge.un";
+                               case 66:
+                                       return "bgt.un";
+                               case 67:
+                                       return "ble.un";
+                               case 68:
+                                       return "blt.un";
+                               case 69:
+                                       return "switch";
+                               case 70:
+                                       return "ldind.i1";
+                               case 71:
+                                       return "ldind.u1";
+                               case 72:
+                                       return "ldind.i2";
+                               case 73:
+                                       return "ldind.u2";
+                               case 74:
+                                       return "ldind.i4";
+                               case 75:
+                                       return "ldind.u4";
+                               case 76:
+                                       return "ldind.i8";
+                               case 77:
+                                       return "ldind.i";
+                               case 78:
+                                       return "ldind.r4";
+                               case 79:
+                                       return "ldind.r8";
+                               case 80:
+                                       return "ldind.ref";
+                               case 81:
+                                       return "stind.ref";
+                               case 82:
+                                       return "stind.i1";
+                               case 83:
+                                       return "stind.i2";
+                               case 84:
+                                       return "stind.i4";
+                               case 85:
+                                       return "stind.i8";
+                               case 86:
+                                       return "stind.r4";
+                               case 87:
+                                       return "stind.r8";
+                               case 88:
+                                       return "add";
+                               case 89:
+                                       return "sub";
+                               case 90:
+                                       return "mul";
+                               case 91:
+                                       return "div";
+                               case 92:
+                                       return "div.un";
+                               case 93:
+                                       return "rem";
+                               case 94:
+                                       return "rem.un";
+                               case 95:
+                                       return "and";
+                               case 96:
+                                       return "or";
+                               case 97:
+                                       return "xor";
+                               case 98:
+                                       return "shl";
+                               case 99:
+                                       return "shr";
+                               case 100:
+                                       return "shr.un";
+                               case 101:
+                                       return "neg";
+                               case 102:
+                                       return "not";
+                               case 103:
+                                       return "conv.i1";
+                               case 104:
+                                       return "conv.i2";
+                               case 105:
+                                       return "conv.i4";
+                               case 106:
+                                       return "conv.i8";
+                               case 107:
+                                       return "conv.r4";
+                               case 108:
+                                       return "conv.r8";
+                               case 109:
+                                       return "conv.u4";
+                               case 110:
+                                       return "conv.u8";
+                               case 111:
+                                       return "callvirt";
+                               case 112:
+                                       return "cpobj";
+                               case 113:
+                                       return "ldobj";
+                               case 114:
+                                       return "ldstr";
+                               case 115:
+                                       return "newobj";
+                               case 116:
+                                       return "castclass";
+                               case 117:
+                                       return "isinst";
+                               case 118:
+                                       return "conv.r.un";
+                               case 121:
+                                       return "unbox";
+                               case 122:
+                                       return "throw";
+                               case 123:
+                                       return "ldfld";
+                               case 124:
+                                       return "ldflda";
+                               case 125:
+                                       return "stfld";
+                               case 126:
+                                       return "ldsfld";
+                               case 127:
+                                       return "ldsflda";
+                               case 128:
+                                       return "stsfld";
+                               case 129:
+                                       return "stobj";
+                               case 130:
+                                       return "conv.ovf.i1.un";
+                               case 131:
+                                       return "conv.ovf.i2.un";
+                               case 132:
+                                       return "conv.ovf.i4.un";
+                               case 133:
+                                       return "conv.ovf.i8.un";
+                               case 134:
+                                       return "conv.ovf.u1.un";
+                               case 135:
+                                       return "conv.ovf.u2.un";
+                               case 136:
+                                       return "conv.ovf.u4.un";
+                               case 137:
+                                       return "conv.ovf.u8.un";
+                               case 138:
+                                       return "conv.ovf.i.un";
+                               case 139:
+                                       return "conv.ovf.u.un";
+                               case 140:
+                                       return "box";
+                               case 141:
+                                       return "newarr";
+                               case 142:
+                                       return "ldlen";
+                               case 143:
+                                       return "ldelema";
+                               case 144:
+                                       return "ldelem.i1";
+                               case 145:
+                                       return "ldelem.u1";
+                               case 146:
+                                       return "ldelem.i2";
+                               case 147:
+                                       return "ldelem.u2";
+                               case 148:
+                                       return "ldelem.i4";
+                               case 149:
+                                       return "ldelem.u4";
+                               case 150:
+                                       return "ldelem.i8";
+                               case 151:
+                                       return "ldelem.i";
+                               case 152:
+                                       return "ldelem.r4";
+                               case 153:
+                                       return "ldelem.r8";
+                               case 154:
+                                       return "ldelem.ref";
+                               case 155:
+                                       return "stelem.i";
+                               case 156:
+                                       return "stelem.i1";
+                               case 157:
+                                       return "stelem.i2";
+                               case 158:
+                                       return "stelem.i4";
+                               case 159:
+                                       return "stelem.i8";
+                               case 160:
+                                       return "stelem.r4";
+                               case 161:
+                                       return "stelem.r8";
+                               case 162:
+                                       return "stelem.ref";
+                               case 163:
+                                       return "ldelem";
+                               case 164:
+                                       return "stelem";
+                               case 165:
+                                       return "unbox.any";
+                               case 179:
+                                       return "conv.ovf.i1";
+                               case 180:
+                                       return "conv.ovf.u1";
+                               case 181:
+                                       return "conv.ovf.i2";
+                               case 182:
+                                       return "conv.ovf.u2";
+                               case 183:
+                                       return "conv.ovf.i4";
+                               case 184:
+                                       return "conv.ovf.u4";
+                               case 185:
+                                       return "conv.ovf.i8";
+                               case 186:
+                                       return "conv.ovf.u8";
+                               case 194:
+                                       return "refanyval";
+                               case 195:
+                                       return "ckfinite";
+                               case 198:
+                                       return "mkrefany";
+                               case 208:
+                                       return "ldtoken";
+                               case 209:
+                                       return "conv.u2";
+                               case 210:
+                                       return "conv.u1";
+                               case 211:
+                                       return "conv.i";
+                               case 212:
+                                       return "conv.ovf.i";
+                               case 213:
+                                       return "conv.ovf.u";
+                               case 214:
+                                       return "add.ovf";
+                               case 215:
+                                       return "add.ovf.un";
+                               case 216:
+                                       return "mul.ovf";
+                               case 217:
+                                       return "mul.ovf.un";
+                               case 218:
+                                       return "sub.ovf";
+                               case 219:
+                                       return "sub.ovf.un";
+                               case 220:
+                                       return "endfinally";
+                               case 221:
+                                       return "leave";
+                               case 222:
+                                       return "leave.s";
+                               case 223:
+                                       return "stind.i";
+                               case 224:
+                                       return "conv.u";
+                               case 248:
+                                       return "prefix7";
+                               case 249:
+                                       return "prefix6";
+                               case 250:
+                                       return "prefix5";
+                               case 251:
+                                       return "prefix4";
+                               case 252:
+                                       return "prefix3";
+                               case 253:
+                                       return "prefix2";
+                               case 254:
+                                       return "prefix1";
+                               case 255:
+                                       return "prefixref";
+                               case -512:
+                                       return "arglist";
+                               case -511:
+                                       return "ceq";
+                               case -510:
+                                       return "cgt";
+                               case -509:
+                                       return "cgt.un";
+                               case -508:
+                                       return "clt";
+                               case -507:
+                                       return "clt.un";
+                               case -506:
+                                       return "ldftn";
+                               case -505:
+                                       return "ldvirtftn";
+                               case -503:
+                                       return "ldarg";
+                               case -502:
+                                       return "ldarga";
+                               case -501:
+                                       return "starg";
+                               case -500:
+                                       return "ldloc";
+                               case -499:
+                                       return "ldloca";
+                               case -498:
+                                       return "stloc";
+                               case -497:
+                                       return "localloc";
+                               case -495:
+                                       return "endfilter";
+                               case -494:
+                                       return "unaligned.";
+                               case -493:
+                                       return "volatile.";
+                               case -492:
+                                       return "tail.";
+                               case -491:
+                                       return "initobj";
+                               case -490:
+                                       return "constrained.";
+                               case -489:
+                                       return "cpblk";
+                               case -488:
+                                       return "initblk";
+                               case -486:
+                                       return "rethrow";
+                               case -484:
+                                       return "sizeof";
+                               case -483:
+                                       return "refanytype";
+                               case -482:
+                                       return "readonly.";
+                       }
+                       throw new ArgumentOutOfRangeException();
+               }
+
+               public static bool TakesSingleByteArgument(OpCode inst)
+               {
+                       switch (inst.Value)
+                       {
+                               case 14:
+                               case 15:
+                               case 16:
+                               case 17:
+                               case 18:
+                               case 19:
+                               case 31:
+                               case 43:
+                               case 44:
+                               case 45:
+                               case 46:
+                               case 47:
+                               case 48:
+                               case 49:
+                               case 50:
+                               case 51:
+                               case 52:
+                               case 53:
+                               case 54:
+                               case 55:
+                               case 222:
+                               case -494:
+                                       return true;
+                               default:
+                                       return false;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/ParameterBuilder.cs b/mcs/class/IKVM.Reflection/Emit/ParameterBuilder.cs
new file mode 100644 (file)
index 0000000..a74e350
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class ParameterBuilder
+       {
+               private readonly ModuleBuilder moduleBuilder;
+               private short flags;
+               private readonly short sequence;
+               private readonly int nameIndex;
+               private readonly string name;
+               private int lazyPseudoToken;
+
+               internal ParameterBuilder(ModuleBuilder moduleBuilder, int sequence, ParameterAttributes attribs, string name)
+               {
+                       this.moduleBuilder = moduleBuilder;
+                       this.flags = (short)attribs;
+                       this.sequence = (short)sequence;
+                       this.nameIndex = name == null ? 0 : moduleBuilder.Strings.Add(name);
+                       this.name = name;
+               }
+
+               internal int PseudoToken
+               {
+                       get
+                       {
+                               if (lazyPseudoToken == 0)
+                               {
+                                       // we lazily create the token, because if we don't need it we don't want the token fixup cost
+                                       lazyPseudoToken = moduleBuilder.AllocPseudoToken();
+                               }
+                               return lazyPseudoToken;
+                       }
+               }
+
+               public string Name
+               {
+                       get { return name; }
+               }
+
+               public int Position
+               {
+                       get { return sequence - 1; }
+               }
+
+               public int Attributes
+               {
+                       get { return flags; }
+               }
+
+               public bool IsIn
+               {
+                       get { return (flags & (short)ParameterAttributes.In) != 0; }
+               }
+
+               public bool IsOut
+               {
+                       get { return (flags & (short)ParameterAttributes.Out) != 0; }
+               }
+
+               public bool IsOptional
+               {
+                       get { return (flags & (short)ParameterAttributes.Optional) != 0; }
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customAttributeBuilder)
+               {
+                       Universe u = moduleBuilder.universe;
+                       if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_InAttribute)
+                       {
+                               flags |= (short)ParameterAttributes.In;
+                       }
+                       else if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_OutAttribute)
+                       {
+                               flags |= (short)ParameterAttributes.Out;
+                       }
+                       else if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_OptionalAttribute)
+                       {
+                               flags |= (short)ParameterAttributes.Optional;
+                       }
+                       else if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_MarshalAsAttribute)
+                       {
+                               MarshalSpec.SetMarshalAsAttribute(moduleBuilder, PseudoToken, customAttributeBuilder);
+                               flags |= (short)ParameterAttributes.HasFieldMarshal;
+                       }
+                       else
+                       {
+                               moduleBuilder.SetCustomAttribute(PseudoToken, customAttributeBuilder);
+                       }
+               }
+
+               public void SetConstant(object defaultValue)
+               {
+                       flags |= (short)ParameterAttributes.HasDefault;
+                       moduleBuilder.AddConstant(PseudoToken, defaultValue);
+               }
+
+               internal void WriteParamRecord(MetadataWriter mw)
+               {
+                       mw.Write(flags);
+                       mw.Write(sequence);
+                       mw.WriteStringIndex(nameIndex);
+               }
+
+               internal void FixupToken(int parameterToken)
+               {
+                       if (lazyPseudoToken != 0)
+                       {
+                               moduleBuilder.RegisterTokenFixup(lazyPseudoToken, parameterToken);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/PropertyBuilder.cs b/mcs/class/IKVM.Reflection/Emit/PropertyBuilder.cs
new file mode 100644 (file)
index 0000000..1815355
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class PropertyBuilder : PropertyInfo
+       {
+               private readonly TypeBuilder typeBuilder;
+               private readonly string name;
+               private PropertyAttributes attributes;
+               private PropertySignature sig;
+               private MethodBuilder getter;
+               private MethodBuilder setter;
+               private List<MethodBuilder> otherMethods;
+               private int lazyPseudoToken;
+               private bool patchCallingConvention;
+
+               internal PropertyBuilder(TypeBuilder typeBuilder, string name, PropertyAttributes attributes, PropertySignature sig, bool patchCallingConvention)
+               {
+                       this.typeBuilder = typeBuilder;
+                       this.name = name;
+                       this.attributes = attributes;
+                       this.sig = sig;
+                       this.patchCallingConvention = patchCallingConvention;
+               }
+
+               internal override PropertySignature PropertySignature
+               {
+                       get { return sig; }
+               }
+
+               private void PatchCallingConvention(MethodBuilder mdBuilder)
+               {
+                       if (patchCallingConvention && !mdBuilder.IsStatic)
+                       {
+                               sig.HasThis = true;
+                       }
+               }
+
+               public void SetGetMethod(MethodBuilder mdBuilder)
+               {
+                       PatchCallingConvention(mdBuilder);
+                       getter = mdBuilder;
+               }
+
+               public void SetSetMethod(MethodBuilder mdBuilder)
+               {
+                       PatchCallingConvention(mdBuilder);
+                       setter = mdBuilder;
+               }
+
+               public void AddOtherMethod(MethodBuilder mdBuilder)
+               {
+                       PatchCallingConvention(mdBuilder);
+                       if (otherMethods == null)
+                       {
+                               otherMethods = new List<MethodBuilder>();
+                       }
+                       otherMethods.Add(mdBuilder);
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       Universe u = typeBuilder.ModuleBuilder.universe;
+                       if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+                       {
+                               attributes |= PropertyAttributes.SpecialName;
+                       }
+                       else
+                       {
+                               if (lazyPseudoToken == 0)
+                               {
+                                       lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+                               }
+                               typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder);
+                       }
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       if (lazyPseudoToken != 0)
+                       {
+                               return typeBuilder.ModuleBuilder.Constant.GetRawConstantValue(typeBuilder.ModuleBuilder, lazyPseudoToken);
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               public override PropertyAttributes Attributes
+               {
+                       get { return attributes; }
+               }
+
+               public override bool CanRead
+               {
+                       get { return getter != null; }
+               }
+
+               public override bool CanWrite
+               {
+                       get { return setter != null; }
+               }
+
+               public override MethodInfo GetGetMethod(bool nonPublic)
+               {
+                       return nonPublic || (getter != null && getter.IsPublic) ? getter : null;
+               }
+
+               public override MethodInfo GetSetMethod(bool nonPublic)
+               {
+                       return nonPublic || (setter != null && setter.IsPublic) ? setter : null;
+               }
+
+               public override MethodInfo[] GetAccessors(bool nonPublic)
+               {
+                       List<MethodInfo> list = new List<MethodInfo>();
+                       AddAccessor(list, nonPublic, getter);
+                       AddAccessor(list, nonPublic, setter);
+                       if (otherMethods != null)
+                       {
+                               foreach (MethodInfo method in otherMethods)
+                               {
+                                       AddAccessor(list, nonPublic, method);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               private static void AddAccessor(List<MethodInfo> list, bool nonPublic, MethodInfo method)
+               {
+                       if (method != null && (nonPublic || method.IsPublic))
+                       {
+                               list.Add(method);
+                       }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeBuilder; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeBuilder.Module; }
+               }
+
+               public void SetConstant(object defaultValue)
+               {
+                       if (lazyPseudoToken == 0)
+                       {
+                               lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+                       }
+                       attributes |= PropertyAttributes.HasDefault;
+                       typeBuilder.ModuleBuilder.AddConstant(lazyPseudoToken, defaultValue);
+               }
+
+               internal void Bake()
+               {
+                       PropertyTable.Record rec = new PropertyTable.Record();
+                       rec.Flags = (short)attributes;
+                       rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name);
+                       rec.Type = typeBuilder.ModuleBuilder.GetSignatureBlobIndex(sig);
+                       int token = 0x17000000 | typeBuilder.ModuleBuilder.Property.AddRecord(rec);
+
+                       if (lazyPseudoToken != 0)
+                       {
+                               typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
+                       }
+
+                       if (getter != null)
+                       {
+                               AddMethodSemantics(MethodSemanticsTable.Getter, getter.MetadataToken, token);
+                       }
+                       if (setter != null)
+                       {
+                               AddMethodSemantics(MethodSemanticsTable.Setter, setter.MetadataToken, token);
+                       }
+                       if (otherMethods != null)
+                       {
+                               foreach (MethodBuilder method in otherMethods)
+                               {
+                                       AddMethodSemantics(MethodSemanticsTable.Other, method.MetadataToken, token);
+                               }
+                       }
+               }
+
+               private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
+               {
+                       MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record();
+                       rec.Semantics = semantics;
+                       rec.Method = methodToken;
+                       rec.Association = propertyToken;
+                       typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec);
+               }
+
+               internal override bool IsPublic
+               {
+                       get
+                       {
+                               if ((getter != null && getter.IsPublic) || (setter != null && setter.IsPublic))
+                               {
+                                       return true;
+                               }
+                               if (otherMethods != null)
+                               {
+                                       foreach (MethodBuilder method in otherMethods)
+                                       {
+                                               if (method.IsPublic)
+                                               {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               return false;
+                       }
+               }
+
+               internal override bool IsStatic
+               {
+                       get
+                       {
+                               if ((getter != null && getter.IsStatic) || (setter != null && setter.IsStatic))
+                               {
+                                       return true;
+                               }
+                               if (otherMethods != null)
+                               {
+                                       foreach (MethodBuilder method in otherMethods)
+                                       {
+                                               if (method.IsStatic)
+                                               {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               return false;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/SignatureHelper.cs b/mcs/class/IKVM.Reflection/Emit/SignatureHelper.cs
new file mode 100644 (file)
index 0000000..788c370
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+  Copyright (C) 2008, 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using IKVM.Reflection;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class SignatureHelper
+       {
+               private readonly ModuleBuilder module;
+               private readonly byte type;
+               private readonly List<Type> args = new List<Type>();
+               private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
+               private readonly List<Type[]> requiredCustomModifiers = new List<Type[]>();
+               private readonly List<Type[]> optionalCustomModifiers = new List<Type[]>();
+               private readonly List<Type> optionalArgs = new List<Type>();
+               private Type returnType;
+               private Type[] returnTypeRequiredCustomModifiers;
+               private Type[] returnTypeOptionalCustomModifiers;
+               private CallingConventions callingConvention;
+               private CallingConvention unmanagedCallConv;
+               private bool unmanaged;
+               private bool optional;
+
+               private SignatureHelper(ModuleBuilder module, byte type)
+               {
+                       this.module = module;
+                       this.type = type;
+               }
+
+               internal bool HasThis
+               {
+                       get { return (callingConvention & CallingConventions.HasThis) != 0; }
+               }
+
+               internal Type ReturnType
+               {
+                       get { return returnType; }
+               }
+
+               internal int ParameterCount
+               {
+                       get { return args.Count + optionalArgs.Count; }
+               }
+
+               public static SignatureHelper GetFieldSigHelper(Module mod)
+               {
+                       return new SignatureHelper(mod as ModuleBuilder, Signature.FIELD);
+               }
+
+               public static SignatureHelper GetLocalVarSigHelper()
+               {
+                       return new SignatureHelper(null, Signature.LOCAL_SIG);
+               }
+
+               public static SignatureHelper GetLocalVarSigHelper(Module mod)
+               {
+                       return new SignatureHelper(mod as ModuleBuilder, Signature.LOCAL_SIG);
+               }
+
+               public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
+               {
+                       SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, Signature.PROPERTY);
+                       sig.returnType = returnType;
+                       sig.returnTypeOptionalCustomModifiers = Type.EmptyTypes;
+                       sig.returnTypeRequiredCustomModifiers = Type.EmptyTypes;
+                       foreach (Type type in parameterTypes)
+                       {
+                               sig.AddArgument(type);
+                       }
+                       return sig;
+               }
+
+               public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+               {
+                       return GetPropertySigHelper(mod, CallingConventions.Standard, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+               }
+
+               public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+               {
+                       SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, Signature.PROPERTY);
+                       sig.callingConvention = callingConvention;
+                       sig.returnType = returnType;
+                       sig.returnTypeOptionalCustomModifiers = requiredReturnTypeCustomModifiers;
+                       sig.returnTypeRequiredCustomModifiers = optionalReturnTypeCustomModifiers;
+                       sig.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+                       return sig;
+               }
+
+               public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)
+               {
+                       return GetMethodSigHelper(null, unmanagedCallingConvention, returnType);
+               }
+
+               public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
+               {
+                       return GetMethodSigHelper(null, callingConvention, returnType);
+               }
+
+               public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
+               {
+                       SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
+                       sig.returnType = returnType;
+                       sig.unmanaged = true;
+                       sig.unmanagedCallConv = unmanagedCallConv;
+                       return sig;
+               }
+
+               public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
+               {
+                       SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
+                       sig.returnType = returnType;
+                       sig.callingConvention = callingConvention;
+                       return sig;
+               }
+
+               public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
+               {
+                       SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
+                       sig.returnType = returnType;
+                       sig.callingConvention = CallingConventions.Standard;
+                       foreach (Type type in parameterTypes)
+                       {
+                               sig.AddArgument(type);
+                       }
+                       return sig;
+               }
+
+               public byte[] GetSignature()
+               {
+                       if (module == null)
+                       {
+                               throw new NotSupportedException();
+                       }
+                       return GetSignature(module).ToArray();
+               }
+
+               internal ByteBuffer GetSignature(ModuleBuilder module)
+               {
+                       ByteBuffer bb = new ByteBuffer(16);
+                       switch (type)
+                       {
+                               case 0:
+                                       if (unmanaged)
+                                       {
+                                               Signature.WriteStandAloneMethodSig(module, bb, unmanagedCallConv, returnType, args.ToArray());
+                                       }
+                                       else
+                                       {
+                                               Signature.WriteStandAloneMethodSig(module, bb, callingConvention, returnType, args.ToArray(), optionalArgs.ToArray());
+                                       }
+                                       break;
+                               case Signature.FIELD:
+                                       FieldSignature.Create(args[0], optionalCustomModifiers[0], requiredCustomModifiers[0]).WriteSig(module, bb);
+                                       break;
+                               case Signature.PROPERTY:
+                                       Signature.WritePropertySig(module, bb, callingConvention, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, args.ToArray(), requiredCustomModifiers.ToArray(), optionalCustomModifiers.ToArray());
+                                       break;
+                               case Signature.LOCAL_SIG:
+                                       Signature.WriteLocalVarSig(module, bb, locals);
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       return bb;
+               }
+
+               public void AddSentinel()
+               {
+                       optional = true;
+                       callingConvention |= CallingConventions.VarArgs;
+               }
+
+               public void AddArgument(Type clsArgument)
+               {
+                       AddArgument(clsArgument, false);
+               }
+
+               public void AddArgument(Type argument, bool pinned)
+               {
+                       AddArgument(argument, pinned, Type.EmptyTypes, Type.EmptyTypes);
+               }
+
+               public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       AddArgument(argument, false, requiredCustomModifiers, optionalCustomModifiers);
+               }
+
+               private void AddArgument(Type argument, bool pinned, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       if (type == Signature.LOCAL_SIG)
+                       {
+                               locals.Add(new LocalBuilder(argument, 0, pinned));
+                       }
+                       else if (optional)
+                       {
+                               this.optionalArgs.Add(argument);
+                       }
+                       else
+                       {
+                               this.args.Add(argument);
+                               this.requiredCustomModifiers.Add(requiredCustomModifiers);
+                               this.optionalCustomModifiers.Add(optionalCustomModifiers);
+                       }
+               }
+
+               public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+               {
+                       for (int i = 0; i < arguments.Length; i++)
+                       {
+                               AddArgument(arguments[i], false, requiredCustomModifiers[i], optionalCustomModifiers[i]);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/Tokens.cs b/mcs/class/IKVM.Reflection/Emit/Tokens.cs
new file mode 100644 (file)
index 0000000..49ac4c6
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+namespace IKVM.Reflection.Emit
+{
+       public struct EventToken
+       {
+               public static readonly EventToken Empty;
+               private readonly int token;
+
+               internal EventToken(int token)
+               {
+                       this.token = token;
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return obj as EventToken? == this;
+               }
+
+               public override int GetHashCode()
+               {
+                       return token;
+               }
+
+               public bool Equals(EventToken other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(EventToken et1, EventToken et2)
+               {
+                       return et1.token == et2.token;
+               }
+
+               public static bool operator !=(EventToken et1, EventToken et2)
+               {
+                       return et1.token != et2.token;
+               }
+       }
+
+       public struct FieldToken
+       {
+               public static readonly FieldToken Empty;
+               private readonly int token;
+
+               internal FieldToken(int token)
+               {
+                       this.token = token;
+               }
+
+               internal bool IsPseudoToken
+               {
+                       get { return token < 0; }
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return obj as FieldToken? == this;
+               }
+
+               public override int GetHashCode()
+               {
+                       return token;
+               }
+
+               public bool Equals(FieldToken other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(FieldToken ft1, FieldToken ft2)
+               {
+                       return ft1.token == ft2.token;
+               }
+
+               public static bool operator !=(FieldToken ft1, FieldToken ft2)
+               {
+                       return ft1.token != ft2.token;
+               }
+       }
+
+       public struct MethodToken
+       {
+               public static readonly MethodToken Empty;
+               private readonly int token;
+
+               internal MethodToken(int token)
+               {
+                       this.token = token;
+               }
+
+               internal bool IsPseudoToken
+               {
+                       get { return token < 0; }
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return obj as MethodToken? == this;
+               }
+
+               public override int GetHashCode()
+               {
+                       return token;
+               }
+
+               public bool Equals(MethodToken other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(MethodToken mt1, MethodToken mt2)
+               {
+                       return mt1.token == mt2.token;
+               }
+
+               public static bool operator !=(MethodToken mt1, MethodToken mt2)
+               {
+                       return mt1.token != mt2.token;
+               }
+       }
+
+       public struct SignatureToken
+       {
+               public static readonly SignatureToken Empty;
+               private readonly int token;
+
+               internal SignatureToken(int token)
+               {
+                       this.token = token;
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return obj as SignatureToken? == this;
+               }
+
+               public override int GetHashCode()
+               {
+                       return token;
+               }
+
+               public bool Equals(SignatureToken other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(SignatureToken st1, SignatureToken st2)
+               {
+                       return st1.token == st2.token;
+               }
+
+               public static bool operator !=(SignatureToken st1, SignatureToken st2)
+               {
+                       return st1.token != st2.token;
+               }
+       }
+
+       public struct StringToken
+       {
+               private readonly int token;
+
+               internal StringToken(int token)
+               {
+                       this.token = token;
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return obj as StringToken? == this;
+               }
+
+               public override int GetHashCode()
+               {
+                       return token;
+               }
+
+               public bool Equals(StringToken other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(StringToken st1, StringToken st2)
+               {
+                       return st1.token == st2.token;
+               }
+
+               public static bool operator !=(StringToken st1, StringToken st2)
+               {
+                       return st1.token != st2.token;
+               }
+       }
+
+       public struct TypeToken
+       {
+               public static readonly TypeToken Empty;
+               private readonly int token;
+
+               internal TypeToken(int token)
+               {
+                       this.token = token;
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return obj as TypeToken? == this;
+               }
+
+               public override int GetHashCode()
+               {
+                       return token;
+               }
+
+               public bool Equals(TypeToken other)
+               {
+                       return this == other;
+               }
+
+               public static bool operator ==(TypeToken tt1, TypeToken tt2)
+               {
+                       return tt1.token == tt2.token;
+               }
+
+               public static bool operator !=(TypeToken tt1, TypeToken tt2)
+               {
+                       return tt1.token != tt2.token;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Emit/TypeBuilder.cs b/mcs/class/IKVM.Reflection/Emit/TypeBuilder.cs
new file mode 100644 (file)
index 0000000..8b2e0eb
--- /dev/null
@@ -0,0 +1,1163 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+       public sealed class GenericTypeParameterBuilder : Type
+       {
+               private readonly string name;
+               private readonly TypeBuilder type;
+               private readonly MethodBuilder method;
+               private readonly int paramPseudoIndex;
+               private readonly int position;
+               private int typeToken;
+               private Type baseType;
+               private GenericParameterAttributes attr;
+
+               internal GenericTypeParameterBuilder(string name, TypeBuilder type, MethodBuilder method, int position)
+               {
+                       this.name = name;
+                       this.type = type;
+                       this.method = method;
+                       this.position = position;
+                       GenericParamTable.Record rec = new GenericParamTable.Record();
+                       rec.Number = (short)position;
+                       rec.Flags = 0;
+                       rec.Owner = type != null ? type.MetadataToken : method.MetadataToken;
+                       rec.Name = this.ModuleBuilder.Strings.Add(name);
+                       this.paramPseudoIndex = this.ModuleBuilder.GenericParam.AddRecord(rec);
+               }
+
+               public override string AssemblyQualifiedName
+               {
+                       get { return null; }
+               }
+
+               public override bool IsValueType
+               {
+                       get { return (this.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; }
+               }
+
+               public override Type BaseType
+               {
+                       get { return baseType; }
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return TypeAttributes.Public; }
+               }
+
+               public override string Namespace
+               {
+                       get { return DeclaringType.Namespace; }
+               }
+
+               public override Type UnderlyingSystemType
+               {
+                       get { return this; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override string FullName
+               {
+                       get { return null; }
+               }
+
+               public override string ToString()
+               {
+                       return this.Name;
+               }
+
+               private ModuleBuilder ModuleBuilder
+               {
+                       get { return type != null ? type.ModuleBuilder : method.ModuleBuilder; }
+               }
+
+               public override Module Module
+               {
+                       get { return ModuleBuilder; }
+               }
+
+               public override bool IsGenericParameter
+               {
+                       get { return true; }
+               }
+
+               public override int GenericParameterPosition
+               {
+                       get { return position; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return type; }
+               }
+
+               public override MethodBase DeclaringMethod
+               {
+                       get { return method; }
+               }
+
+               public override Type[] GetGenericParameterConstraints()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public override GenericParameterAttributes GenericParameterAttributes
+               {
+                       get
+                       {
+                               if (type != null)
+                               {
+                                       type.CheckBaked();
+                               }
+                               else
+                               {
+                                       method.CheckBaked();
+                               }
+                               return attr;
+                       }
+               }
+
+               private void AddConstraint(Type type)
+               {
+                       GenericParamConstraintTable.Record rec = new GenericParamConstraintTable.Record();
+                       rec.Owner = paramPseudoIndex;
+                       rec.Constraint = this.ModuleBuilder.GetTypeTokenForMemberRef(type);
+                       this.ModuleBuilder.GenericParamConstraint.AddRecord(rec);
+               }
+
+               public void SetBaseTypeConstraint(Type baseTypeConstraint)
+               {
+                       this.baseType = baseTypeConstraint;
+                       AddConstraint(baseTypeConstraint);
+               }
+
+               public void SetInterfaceConstraints(params Type[] interfaceConstraints)
+               {
+                       foreach (Type type in interfaceConstraints)
+                       {
+                               AddConstraint(type);
+                       }
+               }
+
+               public void SetGenericParameterAttributes(GenericParameterAttributes genericParameterAttributes)
+               {
+                       this.attr = genericParameterAttributes;
+                       // for now we'll back patch the table
+                       this.ModuleBuilder.GenericParam.PatchAttribute(paramPseudoIndex, genericParameterAttributes);
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       this.ModuleBuilder.SetCustomAttribute((GenericParamTable.Index << 24) | paramPseudoIndex, customBuilder);
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               internal override int GetModuleBuilderToken()
+               {
+                       if (typeToken == 0)
+                       {
+                               ByteBuffer spec = new ByteBuffer(5);
+                               Signature.WriteTypeSpec(this.ModuleBuilder, spec, this);
+                               typeToken = 0x1B000000 | this.ModuleBuilder.TypeSpec.AddRecord(this.ModuleBuilder.Blobs.Add(spec));
+                       }
+                       return typeToken;
+               }
+
+               internal override Type BindTypeParameters(IGenericBinder binder)
+               {
+                       if (type != null)
+                       {
+                               return binder.BindTypeParameter(this);
+                       }
+                       else
+                       {
+                               return binder.BindMethodParameter(this);
+                       }
+               }
+       }
+
+       public sealed class TypeBuilder : Type, ITypeOwner
+       {
+               public const int UnspecifiedTypeSize = 0;
+               private readonly ITypeOwner owner;
+               private readonly int token;
+               private int extends;
+               private Type baseType;
+               private readonly int typeName;
+               private readonly int typeNameSpace;
+               private readonly string nameOrFullName;
+               private readonly List<MethodBuilder> methods = new List<MethodBuilder>();
+               private readonly List<FieldBuilder> fields = new List<FieldBuilder>();
+               private List<PropertyBuilder> properties;
+               private List<EventBuilder> events;
+               private TypeAttributes attribs;
+               private TypeFlags typeFlags;
+               private GenericTypeParameterBuilder[] gtpb;
+               private List<CustomAttributeBuilder> declarativeSecurity;
+               private List<Type> interfaces;
+
+               [Flags]
+               private enum TypeFlags
+               {
+                       IsGenericTypeDefinition = 1,
+                       HasNestedTypes = 2,
+                       Baked = 4,
+               }
+
+               internal TypeBuilder(ITypeOwner owner, string name, Type baseType, TypeAttributes attribs)
+               {
+                       this.owner = owner;
+                       this.token = this.ModuleBuilder.TypeDef.AllocToken();
+                       this.nameOrFullName = TypeNameParser.Escape(name);
+                       SetParent(baseType);
+                       this.attribs = attribs;
+                       if (!this.IsNested)
+                       {
+                               int lastdot = name.LastIndexOf('.');
+                               if (lastdot > 0)
+                               {
+                                       this.typeNameSpace = this.ModuleBuilder.Strings.Add(name.Substring(0, lastdot));
+                                       name = name.Substring(lastdot + 1);
+                               }
+                       }
+                       this.typeName = this.ModuleBuilder.Strings.Add(name);
+               }
+
+               public ConstructorBuilder DefineDefaultConstructor(MethodAttributes attributes)
+               {
+                       ConstructorBuilder cb = DefineConstructor(attributes, CallingConventions.Standard, Type.EmptyTypes);
+                       ILGenerator ilgen = cb.GetILGenerator();
+                       ilgen.Emit(OpCodes.Ldarg_0);
+                       ilgen.Emit(OpCodes.Call, baseType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
+                       ilgen.Emit(OpCodes.Ret);
+                       return cb;
+               }
+
+               public ConstructorBuilder DefineConstructor(MethodAttributes attribs, CallingConventions callConv, Type[] parameterTypes)
+               {
+                       return DefineConstructor(attribs, callConv, parameterTypes, null, null);
+               }
+
+               public ConstructorBuilder DefineConstructor(MethodAttributes attribs, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+               {
+                       attribs |= MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
+                       string name = (attribs & MethodAttributes.Static) == 0 ? ConstructorInfo.ConstructorName : ConstructorInfo.TypeConstructorName;
+                       MethodBuilder mb = DefineMethod(name, attribs, callingConvention, null, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
+                       return new ConstructorBuilder(mb);
+               }
+
+               public ConstructorBuilder DefineTypeInitializer()
+               {
+                       MethodBuilder mb = DefineMethod(ConstructorInfo.TypeConstructorName, MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, null, Type.EmptyTypes);
+                       return new ConstructorBuilder(mb);
+               }
+
+               private MethodBuilder CreateMethodBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention)
+               {
+                       this.ModuleBuilder.MethodDef.AddVirtualRecord();
+                       MethodBuilder mb = new MethodBuilder(this, name, attributes, callingConvention);
+                       methods.Add(mb);
+                       return mb;
+               }
+
+               public MethodBuilder DefineMethod(string name, MethodAttributes attribs)
+               {
+                       return DefineMethod(name, attribs, CallingConventions.Standard);
+               }
+
+               public MethodBuilder DefineMethod(string name, MethodAttributes attribs, CallingConventions callingConvention)
+               {
+                       return CreateMethodBuilder(name, attribs, callingConvention);
+               }
+
+               public MethodBuilder DefineMethod(string name, MethodAttributes attribs, Type returnType, Type[] parameterTypes)
+               {
+                       return DefineMethod(name, attribs, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null);
+               }
+
+               public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       return DefineMethod(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
+               }
+
+               public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       MethodBuilder mb = CreateMethodBuilder(name, attributes, callingConvention);
+                       mb.SetSignature(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+                       return mb;
+               }
+
+               public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+               {
+                       return DefinePInvokeMethod(name, dllName, null, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, nativeCallConv, nativeCharSet);
+               }
+
+               public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+               {
+                       return DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, nativeCallConv, nativeCharSet);
+               }
+
+               public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention,
+                       Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+                       Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+                       CallingConvention nativeCallConv, CharSet nativeCharSet)
+               {
+                       MethodBuilder mb = DefineMethod(name, attributes | MethodAttributes.PinvokeImpl, callingConvention,
+                               returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+                               parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+                       mb.SetDllImportPseudoCustomAttribute(dllName, entryName, nativeCallConv, nativeCharSet, null, null, null, null, null);
+                       return mb;
+               }
+
+               public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
+               {
+                       MethodImplTable.Record rec = new MethodImplTable.Record();
+                       rec.Class = token;
+                       rec.MethodBody = this.ModuleBuilder.GetMethodToken(methodInfoBody).Token;
+                       rec.MethodDeclaration = this.ModuleBuilder.GetMethodToken(methodInfoDeclaration).Token;
+                       this.ModuleBuilder.MethodImpl.AddRecord(rec);
+               }
+
+               public FieldBuilder DefineField(string name, Type fieldType, FieldAttributes attribs)
+               {
+                       return DefineField(name, fieldType, null, null, attribs);
+               }
+
+               public FieldBuilder DefineField(string fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
+               {
+                       FieldBuilder fb = new FieldBuilder(this, fieldName, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
+                       fields.Add(fb);
+                       return fb;
+               }
+
+               public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)
+               {
+                       return DefineProperty(name, attributes, returnType, null, null, parameterTypes, null, null);
+               }
+
+               public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+                       Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       return DefinePropertyImpl(name, attributes, CallingConventions.Standard, true, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+                               parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+               }
+
+               public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention,
+                       Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+                       Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       return DefinePropertyImpl(name, attributes, callingConvention, false, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+                               parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+               }
+
+               private PropertyBuilder DefinePropertyImpl(string name, PropertyAttributes attributes, CallingConventions callingConvention, bool patchCallingConvention,
+                       Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+                       Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       if (properties == null)
+                       {
+                               properties = new List<PropertyBuilder>();
+                       }
+                       PropertySignature sig = PropertySignature.Create(callingConvention, returnType, returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
+                               parameterTypes, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers);
+                       PropertyBuilder pb = new PropertyBuilder(this, name, attributes, sig, patchCallingConvention);
+                       properties.Add(pb);
+                       return pb;
+               }
+
+               public EventBuilder DefineEvent(string name, EventAttributes attributes, Type eventtype)
+               {
+                       if (events == null)
+                       {
+                               events = new List<EventBuilder>();
+                       }
+                       EventBuilder eb = new EventBuilder(this, name, attributes, eventtype);
+                       events.Add(eb);
+                       return eb;
+               }
+
+               public TypeBuilder DefineNestedType(string name)
+               {
+                       return DefineNestedType(name, TypeAttributes.Class | TypeAttributes.NestedPrivate);
+               }
+
+               public TypeBuilder DefineNestedType(string name, TypeAttributes attribs)
+               {
+                       return DefineNestedType(name, attribs, null);
+               }
+
+               public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
+               {
+                       TypeBuilder tb = DefineNestedType(name, attr, parent);
+                       foreach (Type iface in interfaces)
+                       {
+                               tb.AddInterfaceImplementation(iface);
+                       }
+                       return tb;
+               }
+
+               public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent)
+               {
+                       this.typeFlags |= TypeFlags.HasNestedTypes;
+                       return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, PackingSize.Unspecified, 0);
+               }
+
+               public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, int typeSize)
+               {
+                       this.typeFlags |= TypeFlags.HasNestedTypes;
+                       return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, PackingSize.Unspecified, typeSize);
+               }
+
+               public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, PackingSize packSize)
+               {
+                       this.typeFlags |= TypeFlags.HasNestedTypes;
+                       return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, packSize, 0);
+               }
+
+               public void SetParent(Type parent)
+               {
+                       baseType = parent;
+               }
+
+               public void AddInterfaceImplementation(Type interfaceType)
+               {
+                       if (interfaces == null)
+                       {
+                               interfaces = new List<Type>();
+                       }
+                       interfaces.Add(interfaceType);
+               }
+
+               public int Size
+               {
+                       get
+                       {
+                               for (int i = 0; i < this.ModuleBuilder.ClassLayout.records.Length; i++)
+                               {
+                                       if (this.ModuleBuilder.ClassLayout.records[i].Parent == token)
+                                       {
+                                               return this.ModuleBuilder.ClassLayout.records[i].ClassSize;
+                                       }
+                               }
+                               return 0;
+                       }
+               }
+
+               public PackingSize PackingSize
+               {
+                       get
+                       {
+                               for (int i = 0; i < this.ModuleBuilder.ClassLayout.records.Length; i++)
+                               {
+                                       if (this.ModuleBuilder.ClassLayout.records[i].Parent == token)
+                                       {
+                                               return (PackingSize)this.ModuleBuilder.ClassLayout.records[i].PackingSize;
+                                       }
+                               }
+                               return PackingSize.Unspecified;
+                       }
+               }
+
+               private void SetStructLayoutPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       object val = customBuilder.GetConstructorArgument(0);
+                       LayoutKind layout;
+                       if (val is short)
+                       {
+                               layout = (LayoutKind)(short)val;
+                       }
+                       else
+                       {
+                               layout = (LayoutKind)val;
+                       }
+                       int? pack = (int?)customBuilder.GetFieldValue("Pack");
+                       int? size = (int?)customBuilder.GetFieldValue("Size");
+                       if (pack.HasValue || size.HasValue)
+                       {
+                               ClassLayoutTable.Record rec = new ClassLayoutTable.Record();
+                               rec.PackingSize = (short)(pack ?? 0);
+                               rec.ClassSize = size ?? 0;
+                               rec.Parent = token;
+                               this.ModuleBuilder.ClassLayout.AddRecord(rec);
+                       }
+                       attribs &= ~TypeAttributes.LayoutMask;
+                       switch (layout)
+                       {
+                               case LayoutKind.Auto:
+                                       attribs |= TypeAttributes.AutoLayout;
+                                       break;
+                               case LayoutKind.Explicit:
+                                       attribs |= TypeAttributes.ExplicitLayout;
+                                       break;
+                               case LayoutKind.Sequential:
+                                       attribs |= TypeAttributes.SequentialLayout;
+                                       break;
+                       }
+                       CharSet? charSet = customBuilder.GetFieldValue<CharSet>("CharSet");
+                       attribs &= ~TypeAttributes.StringFormatMask;
+                       switch (charSet ?? CharSet.None)
+                       {
+                               case CharSet.None:
+                               case CharSet.Ansi:
+                                       attribs |= TypeAttributes.AnsiClass;
+                                       break;
+                               case CharSet.Auto:
+                                       attribs |= TypeAttributes.AutoClass;
+                                       break;
+                               case CharSet.Unicode:
+                                       attribs |= TypeAttributes.UnicodeClass;
+                                       break;
+                       }
+               }
+
+               public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+               {
+                       SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+               }
+
+               public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+               {
+                       Universe u = this.ModuleBuilder.universe;
+                       Type type = customBuilder.Constructor.DeclaringType;
+                       if (type == u.System_Runtime_InteropServices_StructLayoutAttribute)
+                       {
+                               SetStructLayoutPseudoCustomAttribute(customBuilder.DecodeBlob(this.Assembly));
+                       }
+                       else if (type == u.System_SerializableAttribute)
+                       {
+                               attribs |= TypeAttributes.Serializable;
+                       }
+                       else if (type == u.System_Runtime_InteropServices_ComImportAttribute)
+                       {
+                               attribs |= TypeAttributes.Import;
+                       }
+                       else if (type == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+                       {
+                               attribs |= TypeAttributes.SpecialName;
+                       }
+                       else
+                       {
+                               if (type == u.System_Security_SuppressUnmanagedCodeSecurityAttribute)
+                               {
+                                       attribs |= TypeAttributes.HasSecurity;
+                               }
+                               this.ModuleBuilder.SetCustomAttribute(token, customBuilder);
+                       }
+               }
+
+               public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+               {
+                       attribs |= TypeAttributes.HasSecurity;
+                       if (declarativeSecurity == null)
+                       {
+                               declarativeSecurity = new List<CustomAttributeBuilder>();
+                       }
+                       declarativeSecurity.Add(customBuilder);
+               }
+
+               public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+               {
+                       this.ModuleBuilder.AddDeclarativeSecurity(token, securityAction, permissionSet);
+                       this.attribs |= TypeAttributes.HasSecurity;
+               }
+
+               public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+               {
+                       typeFlags |= TypeFlags.IsGenericTypeDefinition;
+                       gtpb = new GenericTypeParameterBuilder[names.Length];
+                       for (int i = 0; i < names.Length; i++)
+                       {
+                               gtpb[i] = new GenericTypeParameterBuilder(names[i], this, null, i);
+                       }
+                       return (GenericTypeParameterBuilder[])gtpb.Clone();
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       return Util.Copy(gtpb);
+               }
+
+               public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+               {
+                       return gtpb == null ? Empty<Type[]>.Array : Util.Copy(new Type[gtpb.Length][]);
+               }
+
+               public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+               {
+                       return gtpb == null ? Empty<Type[]>.Array : Util.Copy(new Type[gtpb.Length][]);
+               }
+
+               internal override Type GetGenericTypeArgument(int index)
+               {
+                       return gtpb[index];
+               }
+
+               public override bool ContainsGenericParameters
+               {
+                       get { return gtpb != null; }
+               }
+
+               public override Type GetGenericTypeDefinition()
+               {
+                       return this;
+               }
+
+               public Type CreateType()
+               {
+                       if ((typeFlags & TypeFlags.Baked) != 0)
+                       {
+                               // .NET allows multiple invocations (subsequent invocations return the same baked type)
+                               throw new NotImplementedException();
+                       }
+                       typeFlags |= TypeFlags.Baked;
+                       foreach (MethodBuilder mb in methods)
+                       {
+                               mb.Bake();
+                       }
+                       if (declarativeSecurity != null)
+                       {
+                               this.ModuleBuilder.AddDeclarativeSecurity(token, declarativeSecurity);
+                       }
+                       if (baseType != null)
+                       {
+                               extends = this.ModuleBuilder.GetTypeToken(baseType).Token;
+                       }
+                       if (interfaces != null)
+                       {
+                               foreach (Type interfaceType in interfaces)
+                               {
+                                       InterfaceImplTable.Record rec = new InterfaceImplTable.Record();
+                                       rec.Class = token;
+                                       rec.Interface = this.ModuleBuilder.GetTypeToken(interfaceType).Token;
+                                       this.ModuleBuilder.InterfaceImpl.AddRecord(rec);
+                               }
+                       }
+                       return new BakedType(this);
+               }
+
+               internal void PopulatePropertyAndEventTables()
+               {
+                       if (properties != null)
+                       {
+                               PropertyMapTable.Record rec = new PropertyMapTable.Record();
+                               rec.Parent = token;
+                               rec.PropertyList = this.ModuleBuilder.Property.RowCount + 1;
+                               this.ModuleBuilder.PropertyMap.AddRecord(rec);
+                               foreach (PropertyBuilder pb in properties)
+                               {
+                                       pb.Bake();
+                               }
+                       }
+                       if (events != null)
+                       {
+                               EventMapTable.Record rec = new EventMapTable.Record();
+                               rec.Parent = token;
+                               rec.EventList = this.ModuleBuilder.Event.RowCount + 1;
+                               this.ModuleBuilder.EventMap.AddRecord(rec);
+                               foreach (EventBuilder eb in events)
+                               {
+                                       eb.Bake();
+                               }
+                       }
+               }
+
+               public override Type BaseType
+               {
+                       get { return baseType; }
+               }
+
+               public override string FullName
+               {
+                       get
+                       {
+                               if (this.IsNested)
+                               {
+                                       return this.DeclaringType.FullName + "+" + nameOrFullName;
+                               }
+                               else
+                               {
+                                       return nameOrFullName;
+                               }
+                       }
+               }
+
+               public override string Name
+               {
+                       get
+                       {
+                               if (this.IsNested)
+                               {
+                                       return nameOrFullName;
+                               }
+                               else
+                               {
+                                       return base.Name;
+                               }
+                       }
+               }
+
+               public override string Namespace
+               {
+                       get
+                       {
+                               // for some reason, TypeBuilder doesn't return null (and mcs depends on this)
+                               return base.Namespace ?? "";
+                       }
+               }
+
+               internal string GetBakedNamespace()
+               {
+                       // if you refer to the TypeBuilder via its baked Type, Namespace will return null
+                       // for the empty namespace (instead of "" like TypeBuilder.Namespace above does)
+                       return base.Namespace;
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return attribs; }
+               }
+
+               public void __SetAttributes(TypeAttributes attributes)
+               {
+                       this.attribs = attributes;
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       return Util.ToArray(interfaces, Type.EmptyTypes);
+               }
+
+               public override MethodBase[] __GetDeclaredMethods()
+               {
+                       MethodBase[] methods = new MethodBase[this.methods.Count];
+                       for (int i = 0; i < methods.Length; i++)
+                       {
+                               MethodBuilder mb = this.methods[i];
+                               if (mb.IsConstructor)
+                               {
+                                       methods[i] = new ConstructorInfoImpl(mb);
+                               }
+                               else
+                               {
+                                       methods[i] = mb;
+                               }
+                       }
+                       return methods;
+               }
+
+               public override StructLayoutAttribute StructLayoutAttribute
+               {
+                       get
+                       {
+                               StructLayoutAttribute attr;
+                               if ((attribs & TypeAttributes.ExplicitLayout) != 0)
+                               {
+                                       attr = new StructLayoutAttribute(LayoutKind.Explicit);
+                                       attr.Pack = 8;
+                                       attr.Size = 0;
+                                       this.ModuleBuilder.ClassLayout.GetLayout(token, ref attr.Pack, ref attr.Size);
+                               }
+                               else
+                               {
+                                       attr = new StructLayoutAttribute((attribs & TypeAttributes.SequentialLayout) != 0 ? LayoutKind.Sequential : LayoutKind.Auto);
+                                       attr.Pack = 8;
+                                       attr.Size = 0;
+                               }
+                               switch (attribs & TypeAttributes.StringFormatMask)
+                               {
+                                       case TypeAttributes.AutoClass:
+                                               attr.CharSet = CharSet.Auto;
+                                               break;
+                                       case TypeAttributes.UnicodeClass:
+                                               attr.CharSet = CharSet.Unicode;
+                                               break;
+                                       case TypeAttributes.AnsiClass:
+                                               attr.CharSet = CharSet.Ansi;
+                                               break;
+                               }
+                               return attr;
+                       }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return owner as TypeBuilder; }
+               }
+
+               public override bool IsGenericType
+               {
+                       get { return IsGenericTypeDefinition; }
+               }
+
+               public override bool IsGenericTypeDefinition
+               {
+                       get { return (typeFlags & TypeFlags.IsGenericTypeDefinition) != 0; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return token; }
+               }
+
+               public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
+               {
+                       return DefineInitializedData(name, new byte[size], attributes);
+               }
+
+               public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
+               {
+                       Type fieldType = this.ModuleBuilder.GetType("$ArrayType$" + data.Length);
+                       if (fieldType == null)
+                       {
+                               TypeBuilder tb = this.ModuleBuilder.DefineType("$ArrayType$" + data.Length, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout, this.Module.universe.System_ValueType, PackingSize.Size1, data.Length);
+                               tb.CreateType();
+                               fieldType = tb;
+                       }
+                       FieldBuilder fb = DefineField(name, fieldType, attributes | FieldAttributes.Static);
+                       fb.__SetDataAndRVA(data);
+                       return fb;
+               }
+
+               public static MethodInfo GetMethod(Type type, MethodInfo method)
+               {
+                       return new GenericMethodInstance(type, method, null);
+               }
+
+               public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor)
+               {
+                       return new ConstructorInfoImpl(GetMethod(type, constructor.GetMethodInfo()));
+               }
+
+               public static FieldInfo GetField(Type type, FieldInfo field)
+               {
+                       return new GenericFieldInstance(type, field);
+               }
+
+               public override Module Module
+               {
+                       get { return owner.ModuleBuilder; }
+               }
+
+               public TypeToken TypeToken
+               {
+                       get { return new TypeToken(token); }
+               }
+
+               internal void WriteTypeDefRecord(MetadataWriter mw, ref int fieldList, ref int methodList)
+               {
+                       mw.Write((int)attribs);
+                       mw.WriteStringIndex(typeName);
+                       mw.WriteStringIndex(typeNameSpace);
+                       mw.WriteTypeDefOrRef(extends);
+                       mw.WriteField(fieldList);
+                       mw.WriteMethodDef(methodList);
+                       methodList += methods.Count;
+                       fieldList += fields.Count;
+               }
+
+               internal void WriteMethodDefRecords(int baseRVA, MetadataWriter mw, ref int paramList)
+               {
+                       foreach (MethodBuilder mb in methods)
+                       {
+                               mb.WriteMethodDefRecord(baseRVA, mw, ref paramList);
+                       }
+               }
+
+               internal void ResolveMethodAndFieldTokens(ref int methodToken, ref int fieldToken, ref int parameterToken)
+               {
+                       foreach (MethodBuilder method in methods)
+                       {
+                               method.FixupToken(methodToken++, ref parameterToken);
+                       }
+                       foreach (FieldBuilder field in fields)
+                       {
+                               field.FixupToken(fieldToken++);
+                       }
+               }
+
+               internal void WriteParamRecords(MetadataWriter mw)
+               {
+                       foreach (MethodBuilder mb in methods)
+                       {
+                               mb.WriteParamRecords(mw);
+                       }
+               }
+
+               internal void WriteFieldRecords(MetadataWriter mw)
+               {
+                       foreach (FieldBuilder fb in fields)
+                       {
+                               fb.WriteFieldRecords(mw);
+                       }
+               }
+
+               internal ModuleBuilder ModuleBuilder
+               {
+                       get { return owner.ModuleBuilder; }
+               }
+
+               ModuleBuilder ITypeOwner.ModuleBuilder
+               {
+                       get { return owner.ModuleBuilder; }
+               }
+
+               internal override int GetModuleBuilderToken()
+               {
+                       return token;
+               }
+
+               internal bool HasNestedTypes
+               {
+                       get { return (typeFlags & TypeFlags.HasNestedTypes) != 0; }
+               }
+
+               // helper for ModuleBuilder.ResolveMethod()
+               internal MethodBase LookupMethod(int token)
+               {
+                       foreach (MethodBuilder method in methods)
+                       {
+                               if (method.MetadataToken == token)
+                               {
+                                       return method;
+                               }
+                       }
+                       return null;
+               }
+
+               public bool IsCreated()
+               {
+                       return (typeFlags & TypeFlags.Baked) != 0;
+               }
+
+               internal override void CheckBaked()
+               {
+                       if ((typeFlags & TypeFlags.Baked) == 0)
+                       {
+                               throw new NotSupportedException();
+                       }
+               }
+
+               public override Type[] __GetDeclaredTypes()
+               {
+                       if (this.HasNestedTypes)
+                       {
+                               List<Type> types = new List<Type>();
+                               List<int> classes = this.ModuleBuilder.NestedClass.GetNestedClasses(token);
+                               foreach (int nestedClass in classes)
+                               {
+                                       types.Add(this.ModuleBuilder.ResolveType(nestedClass));
+                               }
+                               return types.ToArray();
+                       }
+                       else
+                       {
+                               return Type.EmptyTypes;
+                       }
+               }
+
+               public override FieldInfo[] __GetDeclaredFields()
+               {
+                       return Util.ToArray(fields, Empty<FieldInfo>.Array);
+               }
+
+               public override EventInfo[] __GetDeclaredEvents()
+               {
+                       return Util.ToArray(events, Empty<EventInfo>.Array);
+               }
+
+               public override PropertyInfo[] __GetDeclaredProperties()
+               {
+                       return Util.ToArray(properties, Empty<PropertyInfo>.Array);
+               }
+
+               internal override bool IsModulePseudoType
+               {
+                       get { return token == 0x02000001; }
+               }
+       }
+
+       sealed class BakedType : Type
+       {
+               private readonly TypeBuilder typeBuilder;
+
+               internal BakedType(TypeBuilder typeBuilder)
+               {
+                       this.typeBuilder = typeBuilder;
+               }
+
+               public override string AssemblyQualifiedName
+               {
+                       get { return typeBuilder.AssemblyQualifiedName; }
+               }
+
+               public override Type BaseType
+               {
+                       get { return typeBuilder.BaseType; }
+               }
+
+               public override string Name
+               {
+                       get { return typeBuilder.Name; }
+               }
+
+               public override string Namespace
+               {
+                       get { return typeBuilder.GetBakedNamespace(); }
+               }
+
+               public override string FullName
+               {
+                       get { return typeBuilder.FullName; }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return typeBuilder.Attributes; }
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       return typeBuilder.__GetDeclaredInterfaces();
+               }
+
+               public override MethodBase[] __GetDeclaredMethods()
+               {
+                       return typeBuilder.__GetDeclaredMethods();
+               }
+
+               public override __MethodImplMap __GetMethodImplMap()
+               {
+                       return typeBuilder.__GetMethodImplMap();
+               }
+
+               public override FieldInfo[] __GetDeclaredFields()
+               {
+                       return typeBuilder.__GetDeclaredFields();
+               }
+
+               public override EventInfo[] __GetDeclaredEvents()
+               {
+                       return typeBuilder.__GetDeclaredEvents();
+               }
+
+               public override PropertyInfo[] __GetDeclaredProperties()
+               {
+                       return typeBuilder.__GetDeclaredProperties();
+               }
+
+               public override Type[] __GetDeclaredTypes()
+               {
+                       return typeBuilder.__GetDeclaredTypes();
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeBuilder.DeclaringType; }
+               }
+
+               public override StructLayoutAttribute StructLayoutAttribute
+               {
+                       get { return typeBuilder.StructLayoutAttribute; }
+               }
+
+               public override Type UnderlyingSystemType
+               {
+                       // Type.Equals/GetHashCode relies on this
+                       get { return typeBuilder; }
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       return typeBuilder.GetGenericArguments();
+               }
+
+               internal override Type GetGenericTypeArgument(int index)
+               {
+                       return typeBuilder.GetGenericTypeArgument(index);
+               }
+
+               public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+               {
+                       return typeBuilder.__GetGenericArgumentsOptionalCustomModifiers();
+               }
+
+               public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+               {
+                       return typeBuilder.__GetGenericArgumentsRequiredCustomModifiers();
+               }
+
+               public override bool IsGenericType
+               {
+                       get { return typeBuilder.IsGenericType; }
+               }
+
+               public override bool IsGenericTypeDefinition
+               {
+                       get { return typeBuilder.IsGenericTypeDefinition; }
+               }
+
+               public override bool ContainsGenericParameters
+               {
+                       get { return typeBuilder.ContainsGenericParameters; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return typeBuilder.MetadataToken; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeBuilder.Module; }
+               }
+
+               internal override int GetModuleBuilderToken()
+               {
+                       return typeBuilder.GetModuleBuilderToken();
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Enums.cs b/mcs/class/IKVM.Reflection/Enums.cs
new file mode 100644 (file)
index 0000000..7dd5b34
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+       [Flags]
+       public enum AssemblyNameFlags
+       {
+               None = 0,
+               PublicKey = 1,
+               Retargetable = 256,
+               EnableJITcompileOptimizer = 16384,
+               EnableJITcompileTracking = 32768,
+       }
+
+       [Flags]
+       public enum BindingFlags
+       {
+               Default = 0,
+               DeclaredOnly = 2,
+               Instance = 4,
+               Static = 8,
+               Public = 16,
+               NonPublic = 32,
+               FlattenHierarchy = 64,
+       }
+
+       [Flags]
+       public enum CallingConventions
+       {
+               Standard = 1,
+               VarArgs = 2,
+               Any = 3,
+               HasThis = 32,
+               ExplicitThis = 64,
+       }
+
+       [Flags]
+       public enum EventAttributes
+       {
+               None = 0,
+               SpecialName = 512,
+               RTSpecialName = 1024,
+               ReservedMask = 1024,
+       }
+
+       [Flags]
+       public enum FieldAttributes
+       {
+               PrivateScope = 0,
+               Private = 1,
+               FamANDAssem = 2,
+               Assembly = 3,
+               Family = 4,
+               FamORAssem = 5,
+               Public = 6,
+               FieldAccessMask = 7,
+               Static = 16,
+               InitOnly = 32,
+               Literal = 64,
+               NotSerialized = 128,
+               HasFieldRVA = 256,
+               SpecialName = 512,
+               RTSpecialName = 1024,
+               HasFieldMarshal = 4096,
+               PinvokeImpl = 8192,
+               HasDefault = 32768,
+               ReservedMask = 38144,
+       }
+
+       [Flags]
+       public enum GenericParameterAttributes
+       {
+               None = 0,
+               Covariant = 1,
+               Contravariant = 2,
+               VarianceMask = 3,
+               ReferenceTypeConstraint = 4,
+               NotNullableValueTypeConstraint = 8,
+               DefaultConstructorConstraint = 16,
+               SpecialConstraintMask = 28,
+       }
+
+       public enum ImageFileMachine
+       {
+               I386 = 332,
+               IA64 = 512,
+               AMD64 = 34404,
+       }
+
+       [FlagsAttribute]
+       public enum MemberTypes
+       {
+               Constructor = 0x01,
+               Event = 0x02,
+               Field = 0x04,
+               Method = 0x08,
+               Property = 0x10,
+               TypeInfo = 0x20,
+               Custom = 0x40,
+               NestedType = 0x80,
+               All = Constructor | Event | Field | Method | Property | TypeInfo | NestedType
+       }
+
+       [Flags]
+       public enum MethodAttributes
+       {
+               MemberAccessMask                = 0x0007,
+               PrivateScope                    = 0x0000,
+               Private                                 = 0x0001,
+               FamANDAssem                             = 0x0002,
+               Assembly                                = 0x0003,
+               Family                                  = 0x0004,
+               FamORAssem                              = 0x0005,
+               Public                                  = 0x0006,
+               Static                                  = 0x0010,
+               Final                                   = 0x0020,
+               Virtual                                 = 0x0040,
+               HideBySig                               = 0x0080,
+               VtableLayoutMask                = 0x0100,
+               ReuseSlot                               = 0x0000,
+               NewSlot                                 = 0x0100,
+               CheckAccessOnOverride   = 0x0200,
+               Abstract                                = 0x0400,
+               SpecialName                             = 0x0800,
+
+               PinvokeImpl                             = 0x2000,
+               UnmanagedExport                 = 0x0008,
+
+               RTSpecialName                   = 0x1000,
+               HasSecurity                             = 0x4000,
+               RequireSecObject                = 0x8000,
+
+               ReservedMask                    = 0xd000,
+       }
+
+       [Flags]
+       public enum MethodImplAttributes
+       {
+               CodeTypeMask            = 0x0003,
+               IL                                      = 0x0000,
+               Native                          = 0x0001,
+               OPTIL                           = 0x0002,
+               Runtime                         = 0x0003,
+               ManagedMask                     = 0x0004,
+               Unmanaged                       = 0x0004,
+               Managed                         = 0x0000,
+
+               ForwardRef                      = 0x0010,
+               PreserveSig                     = 0x0080,
+               InternalCall            = 0x1000,
+               Synchronized            = 0x0020,
+               NoInlining                      = 0x0008,
+               NoOptimization          = 0x0040,
+
+               MaxMethodImplVal        = 0xffff,
+       }
+
+       [Flags]
+       public enum ParameterAttributes
+       {
+               None = 0,
+               In = 1,
+               Out = 2,
+               Lcid = 4,
+               Retval = 8,
+               Optional = 16,
+               HasDefault = 4096,
+               HasFieldMarshal = 8192,
+               Reserved3 = 16384,
+               Reserved4 = 32768,
+               ReservedMask = 61440,
+       }
+
+       [Flags]
+       public enum PortableExecutableKinds
+       {
+               NotAPortableExecutableImage = 0,
+               ILOnly = 1,
+               Required32Bit = 2,
+               PE32Plus = 4,
+               Unmanaged32Bit = 8,
+       }
+
+       public enum ProcessorArchitecture
+       {
+               None = 0,
+               MSIL = 1,
+               X86 = 2,
+               IA64 = 3,
+               Amd64 = 4,
+       }
+
+       [Flags]
+       public enum PropertyAttributes
+       {
+               None = 0,
+               SpecialName = 512,
+               RTSpecialName = 1024,
+               HasDefault = 4096,
+       }
+
+       [Flags]
+       public enum ResourceAttributes
+       {
+               Public = 1,
+               Private = 2,
+       }
+
+       public enum ResourceLocation
+       {
+               Embedded = 1,
+               ContainedInAnotherAssembly = 2,
+               ContainedInManifestFile = 4,
+       }
+
+       [Flags]
+       public enum TypeAttributes
+       {
+               AnsiClass = 0,
+               Class = 0,
+               AutoLayout = 0,
+               NotPublic = 0,
+               Public = 1,
+               NestedPublic = 2,
+               NestedPrivate = 3,
+               NestedFamily = 4,
+               NestedAssembly = 5,
+               NestedFamANDAssem = 6,
+               VisibilityMask = 7,
+               NestedFamORAssem = 7,
+               SequentialLayout = 8,
+               ExplicitLayout = 16,
+               LayoutMask = 24,
+               ClassSemanticsMask = 32,
+               Interface = 32,
+               Abstract = 128,
+               Sealed = 256,
+               SpecialName = 1024,
+               RTSpecialName = 2048,
+               Import = 4096,
+               Serializable = 8192,
+               UnicodeClass = 65536,
+               AutoClass = 131072,
+               CustomFormatClass = 196608,
+               StringFormatMask = 196608,
+               HasSecurity = 262144,
+               ReservedMask = 264192,
+               BeforeFieldInit = 1048576,
+               CustomFormatMask = 12582912,
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/EventInfo.cs b/mcs/class/IKVM.Reflection/EventInfo.cs
new file mode 100644 (file)
index 0000000..816acbc
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+namespace IKVM.Reflection
+{
+       public abstract class EventInfo : MemberInfo
+       {
+               public sealed override MemberTypes MemberType
+               {
+                       get { return MemberTypes.Event; }
+               }
+
+               public abstract EventAttributes Attributes { get; }
+               public abstract MethodInfo GetAddMethod(bool nonPublic);
+               public abstract MethodInfo GetRaiseMethod(bool nonPublic);
+               public abstract MethodInfo GetRemoveMethod(bool nonPublic);
+               public abstract MethodInfo[] GetOtherMethods(bool nonPublic);
+               public abstract Type EventHandlerType { get; }
+               internal abstract bool IsPublic { get; }
+               internal abstract bool IsStatic { get; }
+
+               public bool IsSpecialName
+               {
+                       get { return (Attributes & EventAttributes.SpecialName) != 0; }
+               }
+
+               public MethodInfo GetAddMethod()
+               {
+                       return GetAddMethod(false);
+               }
+
+               public MethodInfo GetRaiseMethod()
+               {
+                       return GetRaiseMethod(false);
+               }
+
+               public MethodInfo GetRemoveMethod()
+               {
+                       return GetRemoveMethod(false);
+               }
+
+               public MethodInfo[] GetOtherMethods()
+               {
+                       return GetOtherMethods(false);
+               }
+
+               internal virtual EventInfo BindTypeParameters(Type type)
+               {
+                       return new GenericEventInfo(this.DeclaringType.BindTypeParameters(type), this);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/ExceptionHandlingClause.cs b/mcs/class/IKVM.Reflection/ExceptionHandlingClause.cs
new file mode 100644 (file)
index 0000000..dddc532
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+       public enum ExceptionHandlingClauseOptions
+       {
+               Clause  = 0x0000,
+               Filter  = 0x0001,
+               Finally = 0x0002,
+               Fault   = 0x0004,
+       }
+
+       public sealed class ExceptionHandlingClause
+       {
+               private readonly int flags;
+               private readonly int tryOffset;
+               private readonly int tryLength;
+               private readonly int handlerOffset;
+               private readonly int handlerLength;
+               private readonly Type catchType;
+               private readonly int filterOffset;
+
+               internal ExceptionHandlingClause(ModuleReader module, int flags, int tryOffset, int tryLength, int handlerOffset, int handlerLength, int classTokenOrfilterOffset, IGenericContext context)
+               {
+                       this.flags = flags;
+                       this.tryOffset = tryOffset;
+                       this.tryLength = tryLength;
+                       this.handlerOffset = handlerOffset;
+                       this.handlerLength = handlerLength;
+                       this.catchType = flags == (int)ExceptionHandlingClauseOptions.Clause && classTokenOrfilterOffset != 0 ? module.ResolveType(classTokenOrfilterOffset, context) : null;
+                       this.filterOffset = flags == (int)ExceptionHandlingClauseOptions.Filter ? classTokenOrfilterOffset : 0;
+               }
+
+               public Type CatchType
+               {
+                       get { return catchType; }
+               }
+
+               public int FilterOffset
+               {
+                       get { return filterOffset; }
+               }
+
+               public ExceptionHandlingClauseOptions Flags
+               {
+                       get { return (ExceptionHandlingClauseOptions)flags; }
+               }
+
+               public int HandlerLength
+               {
+                       get { return handlerLength; }
+               }
+
+               public int HandlerOffset
+               {
+                       get { return handlerOffset; }
+               }
+
+               public int TryLength
+               {
+                       get { return tryLength; }
+               }
+
+               public int TryOffset
+               {
+                       get { return tryOffset; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/FieldInfo.cs b/mcs/class/IKVM.Reflection/FieldInfo.cs
new file mode 100644 (file)
index 0000000..b64ea2c
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+       public abstract class FieldInfo : MemberInfo
+       {
+               public sealed override MemberTypes MemberType
+               {
+                       get { return MemberTypes.Field; }
+               }
+
+               public abstract FieldAttributes Attributes { get; }
+               public abstract void __GetDataFromRVA(byte[] data, int offset, int length);
+               public abstract Object GetRawConstantValue();
+               internal abstract FieldSignature FieldSignature { get; }
+
+               public Type FieldType
+               {
+                       get { return this.FieldSignature.FieldType; }
+               }
+
+               public Type[] GetOptionalCustomModifiers()
+               {
+                       return this.FieldSignature.GetOptionalCustomModifiers();
+               }
+
+               public Type[] GetRequiredCustomModifiers()
+               {
+                       return this.FieldSignature.GetRequiredCustomModifiers();
+               }
+
+               public bool IsStatic
+               {
+                       get { return (Attributes & FieldAttributes.Static) != 0; }
+               }
+
+               public bool IsLiteral
+               {
+                       get { return (Attributes & FieldAttributes.Literal) != 0; }
+               }
+
+               public bool IsInitOnly
+               {
+                       get { return (Attributes & FieldAttributes.InitOnly) != 0; }
+               }
+
+               public bool IsNotSerialized
+               {
+                       get { return (Attributes & FieldAttributes.NotSerialized) != 0; }
+               }
+
+               public bool IsSpecialName
+               {
+                       get { return (Attributes & FieldAttributes.SpecialName) != 0; }
+               }
+
+               public bool IsPublic
+               {
+                       get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; }
+               }
+
+               public bool IsPrivate
+               {
+                       get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; }
+               }
+
+               public bool IsFamily
+               {
+                       get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; }
+               }
+
+               public bool IsFamilyOrAssembly
+               {
+                       get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; }
+               }
+
+               public bool IsAssembly
+               {
+                       get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; }
+               }
+
+               public bool IsFamilyAndAssembly
+               {
+                       get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; }
+               }
+
+               public bool IsPinvokeImpl
+               {
+                       get { return (Attributes & FieldAttributes.PinvokeImpl) != 0; }
+               }
+
+               internal abstract int ImportTo(Emit.ModuleBuilder module);
+
+               internal virtual FieldInfo BindTypeParameters(Type type)
+               {
+                       return new GenericFieldInstance(this.DeclaringType.BindTypeParameters(type), this);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/FieldSignature.cs b/mcs/class/IKVM.Reflection/FieldSignature.cs
new file mode 100644 (file)
index 0000000..0a4ff94
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+       sealed class FieldSignature : Signature
+       {
+               private readonly Type fieldType;
+               private readonly Type[] optionalCustomModifiers;
+               private readonly Type[] requiredCustomModifiers;
+
+               internal static FieldSignature Create(Type fieldType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers)
+               {
+                       return new FieldSignature(fieldType, Util.Copy(optionalCustomModifiers), Util.Copy(requiredCustomModifiers));
+               }
+
+               private FieldSignature(Type fieldType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers)
+               {
+                       this.fieldType = fieldType;
+                       this.optionalCustomModifiers = optionalCustomModifiers;
+                       this.requiredCustomModifiers = requiredCustomModifiers;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       FieldSignature other = obj as FieldSignature;
+                       return other != null
+                               && other.fieldType.Equals(fieldType)
+                               && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers)
+                               && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers);
+               }
+
+               public override int GetHashCode()
+               {
+                       return fieldType.GetHashCode() ^ Util.GetHashCode(optionalCustomModifiers) ^ Util.GetHashCode(requiredCustomModifiers);
+               }
+
+               internal Type FieldType
+               {
+                       get { return fieldType; }
+               }
+
+               internal Type[] GetOptionalCustomModifiers()
+               {
+                       return Util.Copy(optionalCustomModifiers);
+               }
+
+               internal Type[] GetRequiredCustomModifiers()
+               {
+                       return Util.Copy(requiredCustomModifiers);
+               }
+
+               internal FieldSignature ExpandTypeParameters(Type declaringType)
+               {
+                       return new FieldSignature(
+                               fieldType.BindTypeParameters(declaringType),
+                               BindTypeParameters(declaringType, optionalCustomModifiers),
+                               BindTypeParameters(declaringType, requiredCustomModifiers));
+               }
+
+               internal static FieldSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       if (br.ReadByte() != FIELD)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       Type fieldType;
+                       Type[] optionalCustomModifiers;
+                       Type[] requiredCustomModifiers;
+                       ReadCustomModifiers(module, br, context, out requiredCustomModifiers, out optionalCustomModifiers);
+                       fieldType = ReadType(module, br, context);
+                       return new FieldSignature(fieldType, optionalCustomModifiers, requiredCustomModifiers);
+               }
+
+               internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
+               {
+                       bb.Write(FIELD);
+                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
+                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
+                       WriteType(module, bb, fieldType);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Fusion.cs b/mcs/class/IKVM.Reflection/Fusion.cs
new file mode 100644 (file)
index 0000000..4e81cd2
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+  Copyright (C) 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       struct ParsedAssemblyName
+       {
+               internal string Name;
+               internal Version Version;
+               internal string Culture;
+               internal string PublicKeyToken;
+       }
+
+       static class Fusion
+       {
+               private static readonly bool UseNativeFusion = Environment.OSVersion.Platform == PlatformID.Win32NT && System.Type.GetType("Mono.Runtime") == null && Environment.GetEnvironmentVariable("IKVM_DISABLE_FUSION") == null;
+
+               internal static bool CompareAssemblyIdentity(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
+               {
+                       if (UseNativeFusion)
+                       {
+                               bool equivalent;
+                               Marshal.ThrowExceptionForHR(CompareAssemblyIdentity(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out equivalent, out result));
+                               return equivalent;
+                       }
+                       else
+                       {
+                               return CompareAssemblyIdentityPure(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result);
+                       }
+               }
+
+               [DllImport("fusion", CharSet = CharSet.Unicode)]
+               private static extern int CompareAssemblyIdentity(string pwzAssemblyIdentity1, bool fUnified1, string pwzAssemblyIdentity2, bool fUnified2, out bool pfEquivalent, out AssemblyComparisonResult pResult);
+
+               private static bool CompareAssemblyIdentityPure(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
+               {
+                       ParsedAssemblyName name1;
+                       ParsedAssemblyName name2;
+
+                       if (!ParseAssemblyName(assemblyIdentity1, out name1)
+                               || !ParseAssemblyName(assemblyIdentity2, out name2))
+                       {
+                               result = AssemblyComparisonResult.NonEquivalent;
+                               throw new ArgumentException();
+                       }
+
+                       bool partial = IsPartial(name1);
+
+                       if ((partial && unified1) || IsPartial(name2))
+                       {
+                               result = AssemblyComparisonResult.NonEquivalent;
+                               throw new ArgumentException();
+                       }
+                       if (!name1.Name.Equals(name2.Name, StringComparison.InvariantCultureIgnoreCase))
+                       {
+                               result = AssemblyComparisonResult.NonEquivalent;
+                               return false;
+                       }
+                       if (name1.Name.Equals("mscorlib", StringComparison.InvariantCultureIgnoreCase))
+                       {
+                               result = AssemblyComparisonResult.EquivalentFullMatch;
+                               return true;
+                       }
+                       if (partial && name1.Culture == null)
+                       {
+                       }
+                       else if (!name1.Culture.Equals(name2.Culture, StringComparison.InvariantCultureIgnoreCase))
+                       {
+                               result = AssemblyComparisonResult.NonEquivalent;
+                               return false;
+                       }
+                       if (IsStrongNamed(name2))
+                       {
+                               if (partial && name1.PublicKeyToken == null)
+                               {
+                               }
+                               else if (name1.PublicKeyToken != name2.PublicKeyToken)
+                               {
+                                       result = AssemblyComparisonResult.NonEquivalent;
+                                       return false;
+                               }
+                               if (partial && name1.Version == null)
+                               {
+                                       result = AssemblyComparisonResult.EquivalentPartialMatch;
+                                       return true;
+                               }
+                               else if (name1.Version < name2.Version)
+                               {
+                                       if (unified2)
+                                       {
+                                               result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified;
+                                               return true;
+                                       }
+                                       else
+                                       {
+                                               result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion;
+                                               return false;
+                                       }
+                               }
+                               else if (name1.Version > name2.Version)
+                               {
+                                       if (unified1)
+                                       {
+                                               result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified;
+                                               return true;
+                                       }
+                                       else
+                                       {
+                                               result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion;
+                                               return false;
+                                       }
+                               }
+                               else
+                               {
+                                       result = partial ? AssemblyComparisonResult.EquivalentPartialMatch : AssemblyComparisonResult.EquivalentFullMatch;
+                                       return true;
+                               }
+                       }
+                       else
+                       {
+                               result = partial ? AssemblyComparisonResult.EquivalentPartialWeakNamed : AssemblyComparisonResult.EquivalentWeakNamed;
+                               return true;
+                       }
+               }
+
+               // note that this is the fusion specific parser, it is not the same as System.Reflection.AssemblyName
+               private static bool ParseAssemblyName(string fullName, out ParsedAssemblyName parsedName)
+               {
+                       parsedName = new ParsedAssemblyName();
+                       StringBuilder sb = new StringBuilder();
+                       int pos = 0;
+                       while (pos < fullName.Length)
+                       {
+                               char ch = fullName[pos++];
+                               if (ch == '\\')
+                               {
+                                       if (pos == fullName.Length)
+                                       {
+                                               return false;
+                                       }
+                                       ch = fullName[pos++];
+                               }
+                               else if (ch == ',')
+                               {
+                                       break;
+                               }
+                               sb.Append(ch);
+                       }
+                       parsedName.Name = sb.ToString().Trim();
+                       if (pos < fullName.Length)
+                       {
+                               string[] parts = fullName.Substring(pos).Split(',');
+                               for (int i = 0; i < parts.Length; i++)
+                               {
+                                       string[] kv = parts[i].Split('=');
+                                       if (kv.Length != 2)
+                                       {
+                                               return false;
+                                       }
+                                       switch (kv[0].Trim().ToLowerInvariant())
+                                       {
+                                               case "version":
+                                                       if (parsedName.Version != null)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       if (!ParseVersion(kv[1].Trim(), out parsedName.Version))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case "culture":
+                                                       if (parsedName.Culture != null)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       if (!ParseCulture(kv[1].Trim(), out parsedName.Culture))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case "publickeytoken":
+                                                       if (parsedName.PublicKeyToken != null)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       if (!ParsePublicKeyToken(kv[1].Trim(), out parsedName.PublicKeyToken))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case "publickey":
+                                                       if (parsedName.PublicKeyToken != null)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       if (!ParsePublicKey(kv[1].Trim(), out parsedName.PublicKeyToken))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+
+               private static bool ParseVersion(string str, out Version version)
+               {
+                       string[] parts = str.Split('.');
+                       if (parts.Length == 4)
+                       {
+                               ushort major, minor, build, revision;
+                               if (ushort.TryParse(parts[0], System.Globalization.NumberStyles.Integer, null, out major)
+                                       && ushort.TryParse(parts[1], System.Globalization.NumberStyles.Integer, null, out minor)
+                                       && ushort.TryParse(parts[2], System.Globalization.NumberStyles.Integer, null, out build)
+                                       && ushort.TryParse(parts[3], System.Globalization.NumberStyles.Integer, null, out revision))
+                               {
+                                       version = new Version(major, minor, build, revision);
+                                       return true;
+                               }
+                       }
+                       version = null;
+                       return false;
+               }
+
+               private static bool ParseCulture(string str, out string culture)
+               {
+                       if (str == null)
+                       {
+                               culture = null;
+                               return false;
+                       }
+                       culture = str;
+                       return true;
+               }
+
+               private static bool ParsePublicKeyToken(string str, out string publicKeyToken)
+               {
+                       if (str == null)
+                       {
+                               publicKeyToken = null;
+                               return false;
+                       }
+                       publicKeyToken = str.ToLowerInvariant();
+                       return true;
+               }
+
+               private static bool ParsePublicKey(string str, out string publicKeyToken)
+               {
+                       if (str == null)
+                       {
+                               publicKeyToken = null;
+                               return false;
+                       }
+                       // HACK use AssemblyName to convert PublicKey to PublicKeyToken
+                       byte[] token = new AssemblyName("Foo, PublicKey=" + str).GetPublicKeyToken();
+                       StringBuilder sb = new StringBuilder(token.Length * 2);
+                       for (int i = 0; i < token.Length; i++)
+                       {
+                               sb.AppendFormat("{0:x2}", token[i]);
+                       }
+                       publicKeyToken = sb.ToString();
+                       return true;
+               }
+
+               private static bool IsPartial(ParsedAssemblyName name)
+               {
+                       return name.Version == null || name.Culture == null || name.PublicKeyToken == null;
+               }
+
+               private static bool IsStrongNamed(ParsedAssemblyName name)
+               {
+                       return name.PublicKeyToken != null && name.PublicKeyToken != "null";
+               }
+
+               private static bool IsEqual(byte[] b1, byte[] b2)
+               {
+                       if (b1.Length != b2.Length)
+                       {
+                               return false;
+                       }
+                       for (int i = 0; i < b1.Length; i++)
+                       {
+                               if (b1[i] != b2[i])
+                               {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/GenericWrappers.cs b/mcs/class/IKVM.Reflection/GenericWrappers.cs
new file mode 100644 (file)
index 0000000..8290f14
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+  Copyright (C) 2009, 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       // this represents both generic method instantiations and non-generic methods on generic type instantations
+       // (this means that it can be a generic method declaration as well as a generic method instance)
+       sealed class GenericMethodInstance : MethodInfo
+       {
+               private readonly Type declaringType;
+               private readonly MethodInfo method;
+               private readonly Type[] methodArgs;
+               private MethodSignature lazyMethodSignature;
+
+               internal GenericMethodInstance(Type declaringType, MethodInfo method, Type[] methodArgs)
+               {
+                       System.Diagnostics.Debug.Assert(!(method is GenericMethodInstance));
+                       this.declaringType = declaringType;
+                       this.method = method;
+                       this.methodArgs = methodArgs;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       GenericMethodInstance other = obj as GenericMethodInstance;
+                       return other != null
+                               && other.method.Equals(method)
+                               && other.declaringType.Equals(declaringType)
+                               && Util.ArrayEquals(other.methodArgs, methodArgs);
+               }
+
+               public override int GetHashCode()
+               {
+                       return declaringType.GetHashCode() * 33 ^ method.GetHashCode() ^ Util.GetHashCode(methodArgs);
+               }
+
+               public override Type ReturnType
+               {
+                       get { return method.ReturnType.BindTypeParameters(this); }
+               }
+
+               public override ParameterInfo ReturnParameter
+               {
+                       get { return new GenericParameterInfoImpl(this, method.ReturnParameter); }
+               }
+
+               public override ParameterInfo[] GetParameters()
+               {
+                       ParameterInfo[] parameters = method.GetParameters();
+                       for (int i = 0; i < parameters.Length; i++)
+                       {
+                               parameters[i] = new GenericParameterInfoImpl(this, parameters[i]);
+                       }
+                       return parameters;
+               }
+
+               internal override int ParameterCount
+               {
+                       get { return method.ParameterCount; }
+               }
+
+               public override CallingConventions CallingConvention
+               {
+                       get { return method.CallingConvention; }
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { return method.Attributes; }
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       return method.GetMethodImplementationFlags();
+               }
+
+               public override string Name
+               {
+                       get { return method.Name; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType.IsModulePseudoType ? null : declaringType; }
+               }
+
+               public override Module Module
+               {
+                       get { return method.Module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return method.MetadataToken; }
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       IKVM.Reflection.Reader.MethodDefImpl md = method as IKVM.Reflection.Reader.MethodDefImpl;
+                       if (md != null)
+                       {
+                               return md.GetMethodBody(this);
+                       }
+                       throw new NotSupportedException();
+               }
+
+               public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+               {
+                       return new GenericMethodInstance(declaringType, method, typeArguments);
+               }
+
+               public override bool IsGenericMethod
+               {
+                       get { return method.IsGenericMethod; }
+               }
+
+               public override bool IsGenericMethodDefinition
+               {
+                       get { return method.IsGenericMethodDefinition && methodArgs == null; }
+               }
+
+               public override bool ContainsGenericParameters
+               {
+                       get
+                       {
+                               if (declaringType.ContainsGenericParameters)
+                               {
+                                       return true;
+                               }
+                               if (methodArgs != null)
+                               {
+                                       foreach (Type type in methodArgs)
+                                       {
+                                               if (type.ContainsGenericParameters)
+                                               {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               return false;
+                       }
+               }
+
+               public override MethodInfo GetGenericMethodDefinition()
+               {
+                       if (this.IsGenericMethod)
+                       {
+                               if (this.IsGenericMethodDefinition)
+                               {
+                                       return this;
+                               }
+                               else if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
+                               {
+                                       return new GenericMethodInstance(declaringType, method, null);
+                               }
+                               else
+                               {
+                                       return method;
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       if (methodArgs == null)
+                       {
+                               return method.GetGenericArguments();
+                       }
+                       else
+                       {
+                               return (Type[])methodArgs.Clone();
+                       }
+               }
+
+               internal override Type GetGenericMethodArgument(int index)
+               {
+                       if (methodArgs == null)
+                       {
+                               return method.GetGenericMethodArgument(index);
+                       }
+                       else
+                       {
+                               return methodArgs[index];
+                       }
+               }
+
+               internal override int GetGenericMethodArgumentCount()
+               {
+                       return method.GetGenericMethodArgumentCount();
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return method.GetCustomAttributesData(attributeType);
+               }
+
+               internal override MethodInfo GetMethodOnTypeDefinition()
+               {
+                       return method.GetMethodOnTypeDefinition();
+               }
+
+               internal override int ImportTo(Emit.ModuleBuilder module)
+               {
+                       if (methodArgs == null)
+                       {
+                               return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
+                       }
+                       else
+                       {
+                               Writer.ByteBuffer spec = new Writer.ByteBuffer(10);
+                               Signature.WriteMethodSpec(module, spec, methodArgs);
+                               Metadata.MethodSpecTable.Record rec = new Metadata.MethodSpecTable.Record();
+                               Emit.MethodBuilder mb = method as Emit.MethodBuilder;
+                               if (mb != null && mb.ModuleBuilder == module && !declaringType.IsGenericType)
+                               {
+                                       rec.Method = mb.MetadataToken;
+                               }
+                               else
+                               {
+                                       rec.Method = module.ImportMember(GetGenericMethodDefinition());
+                               }
+                               rec.Instantiation = module.Blobs.Add(spec);
+                               return 0x2B000000 | module.MethodSpec.FindOrAddRecord(rec);
+                       }
+               }
+
+               internal override MethodSignature MethodSignature
+               {
+                       get { return lazyMethodSignature ?? (lazyMethodSignature = method.MethodSignature.Bind(declaringType, methodArgs)); }
+               }
+
+               internal override MethodBase BindTypeParameters(Type type)
+               {
+                       System.Diagnostics.Debug.Assert(methodArgs == null);
+                       return new GenericMethodInstance(declaringType.BindTypeParameters(type), method, null);
+               }
+       }
+
+       sealed class GenericFieldInstance : FieldInfo
+       {
+               private readonly Type declaringType;
+               private readonly FieldInfo field;
+
+               internal GenericFieldInstance(Type declaringType, FieldInfo field)
+               {
+                       this.declaringType = declaringType;
+                       this.field = field;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       GenericFieldInstance other = obj as GenericFieldInstance;
+                       return other != null && other.declaringType.Equals(declaringType) && other.field.Equals(field);
+               }
+
+               public override int GetHashCode()
+               {
+                       return declaringType.GetHashCode() * 3 ^ field.GetHashCode();
+               }
+
+               public override FieldAttributes Attributes
+               {
+                       get { return field.Attributes; }
+               }
+
+               public override string Name
+               {
+                       get { return field.Name; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType; }
+               }
+
+               public override Module Module
+               {
+                       get { return declaringType.Module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return field.MetadataToken; }
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       return field.GetRawConstantValue();
+               }
+
+               public override void __GetDataFromRVA(byte[] data, int offset, int length)
+               {
+                       field.__GetDataFromRVA(data, offset, length);
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return field.GetCustomAttributesData(attributeType);
+               }
+
+               internal override FieldSignature FieldSignature
+               {
+                       get { return field.FieldSignature.ExpandTypeParameters(declaringType); }
+               }
+
+               internal override int ImportTo(Emit.ModuleBuilder module)
+               {
+                       return module.ImportMethodOrField(declaringType, field.Name, field.FieldSignature);
+               }
+
+               internal override FieldInfo BindTypeParameters(Type type)
+               {
+                       return new GenericFieldInstance(declaringType.BindTypeParameters(type), field);
+               }
+       }
+
+       sealed class GenericParameterInfoImpl : ParameterInfo
+       {
+               private readonly GenericMethodInstance method;
+               private readonly ParameterInfo parameterInfo;
+
+               internal GenericParameterInfoImpl(GenericMethodInstance method, ParameterInfo parameterInfo)
+               {
+                       this.method = method;
+                       this.parameterInfo = parameterInfo;
+               }
+
+               public override string Name
+               {
+                       get { return parameterInfo.Name; }
+               }
+
+               public override Type ParameterType
+               {
+                       get { return parameterInfo.ParameterType.BindTypeParameters(method); }
+               }
+
+               public override ParameterAttributes Attributes
+               {
+                       get { return parameterInfo.Attributes; }
+               }
+
+               public override int Position
+               {
+                       get { return parameterInfo.Position; }
+               }
+
+               public override object RawDefaultValue
+               {
+                       get { return parameterInfo.RawDefaultValue; }
+               }
+
+               public override Type[] GetOptionalCustomModifiers()
+               {
+                       Type[] modifiers = parameterInfo.GetOptionalCustomModifiers();
+                       Type.InplaceBindTypeParameters(method, modifiers);
+                       return modifiers;
+               }
+
+               public override Type[] GetRequiredCustomModifiers()
+               {
+                       Type[] modifiers = parameterInfo.GetRequiredCustomModifiers();
+                       Type.InplaceBindTypeParameters(method, modifiers);
+                       return modifiers;
+               }
+
+               public override MemberInfo Member
+               {
+                       get { return method; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return parameterInfo.MetadataToken; }
+               }
+
+               internal override Module Module
+               {
+                       get { return method.Module; }
+               }
+       }
+
+       sealed class GenericPropertyInfo : PropertyInfo
+       {
+               private readonly Type typeInstance;
+               private readonly PropertyInfo property;
+
+               internal GenericPropertyInfo(Type typeInstance, PropertyInfo property)
+               {
+                       this.typeInstance = typeInstance;
+                       this.property = property;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       GenericPropertyInfo other = obj as GenericPropertyInfo;
+                       return other != null && other.typeInstance == typeInstance && other.property == property;
+               }
+
+               public override int GetHashCode()
+               {
+                       return typeInstance.GetHashCode() * 537 + property.GetHashCode();
+               }
+
+               public override PropertyAttributes Attributes
+               {
+                       get { return property.Attributes; }
+               }
+
+               public override bool CanRead
+               {
+                       get { return property.CanRead; }
+               }
+
+               public override bool CanWrite
+               {
+                       get { return property.CanWrite; }
+               }
+
+               private MethodInfo Wrap(MethodInfo method)
+               {
+                       if (method == null)
+                       {
+                               return null;
+                       }
+                       return new GenericMethodInstance(typeInstance, method, null);
+               }
+
+               public override MethodInfo GetGetMethod(bool nonPublic)
+               {
+                       return Wrap(property.GetGetMethod(nonPublic));
+               }
+
+               public override MethodInfo GetSetMethod(bool nonPublic)
+               {
+                       return Wrap(property.GetSetMethod(nonPublic));
+               }
+
+               public override MethodInfo[] GetAccessors(bool nonPublic)
+               {
+                       MethodInfo[] accessors = property.GetAccessors(nonPublic);
+                       for (int i = 0; i < accessors.Length; i++)
+                       {
+                               accessors[i] = Wrap(accessors[i]);
+                       }
+                       return accessors;
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       return property.GetRawConstantValue();
+               }
+
+               internal override bool IsPublic
+               {
+                       get { return property.IsPublic; }
+               }
+
+               internal override bool IsStatic
+               {
+                       get { return property.IsStatic; }
+               }
+
+               internal override PropertySignature PropertySignature
+               {
+                       get { return property.PropertySignature.ExpandTypeParameters(typeInstance); }
+               }
+
+               public override string Name
+               {
+                       get { return property.Name; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeInstance; }
+               }
+
+               public override Module Module
+               {
+                       get { return typeInstance.Module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return property.MetadataToken; }
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return property.GetCustomAttributesData(attributeType);
+               }
+
+               internal override PropertyInfo BindTypeParameters(Type type)
+               {
+                       return new GenericPropertyInfo(typeInstance.BindTypeParameters(type), property);
+               }
+       }
+
+       sealed class GenericEventInfo : EventInfo
+       {
+               private readonly Type typeInstance;
+               private readonly EventInfo eventInfo;
+
+               internal GenericEventInfo(Type typeInstance, EventInfo eventInfo)
+               {
+                       this.typeInstance = typeInstance;
+                       this.eventInfo = eventInfo;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       GenericEventInfo other = obj as GenericEventInfo;
+                       return other != null && other.typeInstance == typeInstance && other.eventInfo == eventInfo;
+               }
+
+               public override int GetHashCode()
+               {
+                       return typeInstance.GetHashCode() * 777 + eventInfo.GetHashCode();
+               }
+
+               public override EventAttributes Attributes
+               {
+                       get { return eventInfo.Attributes; }
+               }
+
+               private MethodInfo Wrap(MethodInfo method)
+               {
+                       if (method == null)
+                       {
+                               return null;
+                       }
+                       return new GenericMethodInstance(typeInstance, method, null);
+               }
+
+               public override MethodInfo GetAddMethod(bool nonPublic)
+               {
+                       return Wrap(eventInfo.GetAddMethod(nonPublic));
+               }
+
+               public override MethodInfo GetRaiseMethod(bool nonPublic)
+               {
+                       return Wrap(eventInfo.GetRaiseMethod(nonPublic));
+               }
+
+               public override MethodInfo GetRemoveMethod(bool nonPublic)
+               {
+                       return Wrap(eventInfo.GetRemoveMethod(nonPublic));
+               }
+
+               public override MethodInfo[] GetOtherMethods(bool nonPublic)
+               {
+                       MethodInfo[] others = eventInfo.GetOtherMethods(nonPublic);
+                       for (int i = 0; i < others.Length; i++)
+                       {
+                               others[i] = Wrap(others[i]);
+                       }
+                       return others;
+               }
+
+               public override Type EventHandlerType
+               {
+                       get { return eventInfo.EventHandlerType.BindTypeParameters(typeInstance); }
+               }
+
+               public override string Name
+               {
+                       get { return eventInfo.Name; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return typeInstance; }
+               }
+
+               public override Module Module
+               {
+                       get { return eventInfo.Module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return eventInfo.MetadataToken; }
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return eventInfo.GetCustomAttributesData(attributeType);
+               }
+
+               internal override EventInfo BindTypeParameters(Type type)
+               {
+                       return new GenericEventInfo(typeInstance.BindTypeParameters(type), eventInfo);
+               }
+
+               internal override bool IsPublic
+               {
+                       get { return eventInfo.IsPublic; }
+               }
+
+               internal override bool IsStatic
+               {
+                       get { return eventInfo.IsStatic; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/IKVM.Reflection.csproj b/mcs/class/IKVM.Reflection/IKVM.Reflection.csproj
new file mode 100644 (file)
index 0000000..c038274
--- /dev/null
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>IKVM.Reflection</RootNamespace>
+    <AssemblyName>IKVM.Reflection</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkSubset>
+    </TargetFrameworkSubset>
+    <SccProjectName>
+    </SccProjectName>
+    <SccLocalPath>
+    </SccLocalPath>
+    <SccAuxPath>
+    </SccAuxPath>
+    <SccProvider>
+    </SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="AmbiguousMatchException.cs" />
+    <Compile Include="Assembly.cs" />
+    <Compile Include="AssemblyName.cs" />
+    <Compile Include="BadImageFormatException.cs" />
+    <Compile Include="Binder.cs" />
+    <Compile Include="ConstructorInfo.cs" />
+    <Compile Include="CustomAttributeData.cs" />
+    <Compile Include="CustomAttributeNamedArgument.cs" />
+    <Compile Include="CustomAttributeTypedArgument.cs" />
+    <Compile Include="Emit\AssemblyBuilder.cs" />
+    <Compile Include="Emit\ConstructorBuilder.cs" />
+    <Compile Include="Emit\CustomAttributeBuilder.cs" />
+    <Compile Include="Emit\EnumBuilder.cs" />
+    <Compile Include="Emit\Enums.cs" />
+    <Compile Include="Emit\EventBuilder.cs" />
+    <Compile Include="Emit\FieldBuilder.cs" />
+    <Compile Include="Emit\ILGenerator.cs" />
+    <Compile Include="Emit\MethodBuilder.cs" />
+    <Compile Include="Emit\ModuleBuilder.cs" />
+    <Compile Include="Emit\OpCode.cs" />
+    <Compile Include="Emit\OpCodes.cs" />
+    <Compile Include="Emit\ParameterBuilder.cs" />
+    <Compile Include="Emit\PropertyBuilder.cs" />
+    <Compile Include="Emit\SignatureHelper.cs" />
+    <Compile Include="Emit\Tokens.cs" />
+    <Compile Include="Emit\TypeBuilder.cs" />
+    <Compile Include="Enums.cs" />
+    <Compile Include="EventInfo.cs" />
+    <Compile Include="ExceptionHandlingClause.cs" />
+    <Compile Include="FieldInfo.cs" />
+    <Compile Include="FieldSignature.cs" />
+    <Compile Include="Fusion.cs" />
+    <Compile Include="GenericWrappers.cs" />
+    <Compile Include="Impl\CryptoConvert.cs" />
+    <Compile Include="Impl\CryptoHack.cs" />
+    <Compile Include="Impl\ITypeOwner.cs" />
+    <Compile Include="Impl\MdbWriter.cs" />
+    <Compile Include="Impl\PdbWriter.cs" />
+    <Compile Include="Impl\SymbolSupport.cs" />
+    <Compile Include="InterfaceMapping.cs" />
+    <Compile Include="LocalVariableInfo.cs" />
+    <Compile Include="ManifestResourceInfo.cs" />
+    <Compile Include="MarshalSpec.cs" />
+    <Compile Include="MemberInfo.cs" />
+    <Compile Include="Metadata\CliHeader.cs" />
+    <Compile Include="Metadata\MetadataRW.cs" />
+    <Compile Include="Metadata\Tables.cs" />
+    <Compile Include="MethodBase.cs" />
+    <Compile Include="MethodBody.cs" />
+    <Compile Include="MethodImplMap.cs" />
+    <Compile Include="MethodInfo.cs" />
+    <Compile Include="MethodSignature.cs" />
+    <Compile Include="Module.cs" />
+    <Compile Include="ParameterInfo.cs" />
+    <Compile Include="ParameterModifier.cs" />
+    <Compile Include="PropertyInfo.cs" />
+    <Compile Include="PropertySignature.cs" />
+    <Compile Include="Reader\AssemblyReader.cs" />
+    <Compile Include="Reader\ByteReader.cs" />
+    <Compile Include="Reader\EventInfoImpl.cs" />
+    <Compile Include="Reader\Field.cs" />
+    <Compile Include="Reader\GenericTypeParameter.cs" />
+    <Compile Include="Reader\MetadataReader.cs" />
+    <Compile Include="Reader\Method.cs" />
+    <Compile Include="Reader\ModuleReader.cs" />
+    <Compile Include="Reader\PEReader.cs" />
+    <Compile Include="Reader\PropertyInfoImpl.cs" />
+    <Compile Include="Reader\ResourceModule.cs" />
+    <Compile Include="Reader\TypeDefImpl.cs" />
+    <Compile Include="Signature.cs" />
+    <Compile Include="StandAloneMethodSig.cs" />
+    <Compile Include="StrongNameKeyPair.cs" />
+    <Compile Include="Type.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TypeNameParser.cs" />
+    <Compile Include="Universe.cs" />
+    <Compile Include="Util.cs" />
+    <Compile Include="Writer\ByteBuffer.cs" />
+    <Compile Include="Writer\Heaps.cs" />
+    <Compile Include="Writer\MetadataWriter.cs" />
+    <Compile Include="Writer\ModuleWriter.cs" />
+    <Compile Include="Writer\PEWriter.cs" />
+    <Compile Include="Writer\ResourceSection.cs" />
+    <Compile Include="Writer\TextSection.cs" />
+    <Compile Include="Writer\VersionInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/mcs/class/IKVM.Reflection/Impl/CryptoConvert.cs b/mcs/class/IKVM.Reflection/Impl/CryptoConvert.cs
new file mode 100644 (file)
index 0000000..14687de
--- /dev/null
@@ -0,0 +1,743 @@
+//
+// CryptoConvert.cs - Crypto Convertion Routines
+//
+// Author:
+//     Sebastien Pouliot  <sebastien@ximian.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [JF-20081013] begin modifications for IKVM
+#define INSIDE_CORLIB
+// end modifications for IKVM
+
+using System;
+using System.Globalization;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Mono.Security.Cryptography {
+
+#if INSIDE_CORLIB
+       internal
+#else
+       public
+#endif
+       sealed class CryptoConvert {
+
+               private CryptoConvert () 
+               {
+               }
+
+               static private int ToInt32LE (byte [] bytes, int offset)
+               {
+                       return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset];
+               }
+
+               static private uint ToUInt32LE (byte [] bytes, int offset)
+               {
+                       return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]);
+               }
+
+               static private byte [] GetBytesLE (int val)
+               {
+                       return new byte [] { 
+                               (byte) (val & 0xff), 
+                               (byte) ((val >> 8) & 0xff), 
+                               (byte) ((val >> 16) & 0xff), 
+                               (byte) ((val >> 24) & 0xff)
+                       };
+                }
+
+               static private byte[] Trim (byte[] array) 
+               {
+                       for (int i=0; i < array.Length; i++) {
+                               if (array [i] != 0x00) {
+                                       byte[] result = new byte [array.Length - i];
+                                       Buffer.BlockCopy (array, i, result, 0, result.Length);
+                                       return result;
+                               }
+                       }
+                       return null;
+               }
+
+               // convert the key from PRIVATEKEYBLOB to RSA
+               // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/Security/private_key_blobs.asp
+               // e.g. SNK files, PVK files
+               static public RSA FromCapiPrivateKeyBlob (byte[] blob) 
+               {
+                       return FromCapiPrivateKeyBlob (blob, 0);
+               }
+
+               static public RSA FromCapiPrivateKeyBlob (byte[] blob, int offset) 
+               {
+                       if (blob == null)
+                               throw new ArgumentNullException ("blob");
+                       if (offset >= blob.Length)
+                               throw new ArgumentException ("blob is too small.");
+
+                       RSAParameters rsap = new RSAParameters ();
+                       try {
+                               if ((blob [offset]   != 0x07) ||                                // PRIVATEKEYBLOB (0x07)
+                                   (blob [offset+1] != 0x02) ||                                // Version (0x02)
+                                   (blob [offset+2] != 0x00) ||                                // Reserved (word)
+                                   (blob [offset+3] != 0x00) ||
+                                   (ToUInt32LE (blob, offset+8) != 0x32415352))        // DWORD magic = RSA2
+                                       throw new CryptographicException ("Invalid blob header");
+                               
+                               // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+                               // int algId = ToInt32LE (blob, offset+4);
+
+                               // DWORD bitlen
+                               int bitLen = ToInt32LE (blob, offset+12);
+
+                               // DWORD public exponent
+                               byte[] exp = new byte [4];
+                               Buffer.BlockCopy (blob, offset+16, exp, 0, 4);
+                               Array.Reverse (exp);
+                               rsap.Exponent = Trim (exp);
+                       
+                               int pos = offset+20;
+                               // BYTE modulus[rsapubkey.bitlen/8];
+                               int byteLen = (bitLen >> 3);
+                               rsap.Modulus = new byte [byteLen];
+                               Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
+                               Array.Reverse (rsap.Modulus);
+                               pos += byteLen;
+
+                               // BYTE prime1[rsapubkey.bitlen/16];
+                               int byteHalfLen = (byteLen >> 1);
+                               rsap.P = new byte [byteHalfLen];
+                               Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen);
+                               Array.Reverse (rsap.P);
+                               pos += byteHalfLen;
+
+                               // BYTE prime2[rsapubkey.bitlen/16];
+                               rsap.Q = new byte [byteHalfLen];
+                               Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen);
+                               Array.Reverse (rsap.Q);
+                               pos += byteHalfLen;
+
+                               // BYTE exponent1[rsapubkey.bitlen/16];
+                               rsap.DP = new byte [byteHalfLen];
+                               Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen);
+                               Array.Reverse (rsap.DP);
+                               pos += byteHalfLen;
+
+                               // BYTE exponent2[rsapubkey.bitlen/16];
+                               rsap.DQ = new byte [byteHalfLen];
+                               Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen);
+                               Array.Reverse (rsap.DQ);
+                               pos += byteHalfLen;
+
+                               // BYTE coefficient[rsapubkey.bitlen/16];
+                               rsap.InverseQ = new byte [byteHalfLen];
+                               Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen);
+                               Array.Reverse (rsap.InverseQ);
+                               pos += byteHalfLen;
+
+                               // ok, this is hackish but CryptoAPI support it so...
+                               // note: only works because CRT is used by default
+                               // http://bugzilla.ximian.com/show_bug.cgi?id=57941
+                               rsap.D = new byte [byteLen]; // must be allocated
+                               if (pos + byteLen + offset <= blob.Length) {
+                                       // BYTE privateExponent[rsapubkey.bitlen/8];
+                                       Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen);
+                                       Array.Reverse (rsap.D);
+                               }
+                       }
+                       catch (Exception e) {
+                               throw new CryptographicException ("Invalid blob.", e);
+                       }
+
+                       RSA rsa = null;
+                       try {
+                               rsa = RSA.Create ();
+                               rsa.ImportParameters (rsap);
+                       }
+                       catch (CryptographicException ce) {
+                               // this may cause problem when this code is run under
+                               // the SYSTEM identity on Windows (e.g. ASP.NET). See
+                               // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+                               try {
+                                       CspParameters csp = new CspParameters ();
+                                       csp.Flags = CspProviderFlags.UseMachineKeyStore;
+                                       rsa = new RSACryptoServiceProvider (csp);
+                                       rsa.ImportParameters (rsap);
+                               }
+                               catch {
+                                       // rethrow original, not the later, exception if this fails
+                                       throw ce;
+                               }
+                       }
+                       return rsa;
+               }
+
+               static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob)
+               {
+                       return FromCapiPrivateKeyBlobDSA (blob, 0);
+               }
+
+               static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob, int offset)
+               {
+                       if (blob == null)
+                               throw new ArgumentNullException ("blob");
+                       if (offset >= blob.Length)
+                               throw new ArgumentException ("blob is too small.");
+
+                       DSAParameters dsap = new DSAParameters ();
+                       try {
+                               if ((blob [offset] != 0x07) ||                          // PRIVATEKEYBLOB (0x07)
+                                   (blob [offset + 1] != 0x02) ||                      // Version (0x02)
+                                   (blob [offset + 2] != 0x00) ||                      // Reserved (word)
+                                   (blob [offset + 3] != 0x00) ||
+                                   (ToUInt32LE (blob, offset + 8) != 0x32535344))      // DWORD magic
+                                       throw new CryptographicException ("Invalid blob header");
+
+                               int bitlen = ToInt32LE (blob, offset + 12);
+                               int bytelen = bitlen >> 3;
+                               int pos = offset + 16;
+
+                               dsap.P = new byte [bytelen];
+                               Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen);
+                               Array.Reverse (dsap.P);
+                               pos += bytelen;
+
+                               dsap.Q = new byte [20];
+                               Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20);
+                               Array.Reverse (dsap.Q);
+                               pos += 20;
+
+                               dsap.G = new byte [bytelen];
+                               Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen);
+                               Array.Reverse (dsap.G);
+                               pos += bytelen;
+
+                               dsap.X = new byte [20];
+                               Buffer.BlockCopy (blob, pos, dsap.X, 0, 20);
+                               Array.Reverse (dsap.X);
+                               pos += 20;
+
+                               dsap.Counter = ToInt32LE (blob, pos);
+                               pos += 4;
+
+                               dsap.Seed = new byte [20];
+                               Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20);
+                               Array.Reverse (dsap.Seed);
+                               pos += 20;
+                       }
+                       catch (Exception e) {
+                               throw new CryptographicException ("Invalid blob.", e);
+                       }
+
+                       DSA dsa = null;
+                       try {
+                               dsa = (DSA)DSA.Create ();
+                               dsa.ImportParameters (dsap);
+                       }
+                       catch (CryptographicException ce) {
+                               // this may cause problem when this code is run under
+                               // the SYSTEM identity on Windows (e.g. ASP.NET). See
+                               // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+                               try {
+                                       CspParameters csp = new CspParameters ();
+                                       csp.Flags = CspProviderFlags.UseMachineKeyStore;
+                                       dsa = new DSACryptoServiceProvider (csp);
+                                       dsa.ImportParameters (dsap);
+                               }
+                               catch {
+                                       // rethrow original, not the later, exception if this fails
+                                       throw ce;
+                               }
+                       }
+                       return dsa;
+               }
+
+               static public byte[] ToCapiPrivateKeyBlob (RSA rsa) 
+               {
+                       RSAParameters p = rsa.ExportParameters (true);
+                       int keyLength = p.Modulus.Length; // in bytes
+                       byte[] blob = new byte [20 + (keyLength << 2) + (keyLength >> 1)];
+
+                       blob [0] = 0x07;        // Type - PRIVATEKEYBLOB (0x07)
+                       blob [1] = 0x02;        // Version - Always CUR_BLOB_VERSION (0x02)
+                       // [2], [3]             // RESERVED - Always 0
+                       blob [5] = 0x24;        // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+                       blob [8] = 0x52;        // Magic - RSA2 (ASCII in hex)
+                       blob [9] = 0x53;
+                       blob [10] = 0x41;
+                       blob [11] = 0x32;
+
+                       byte[] bitlen = GetBytesLE (keyLength << 3);
+                       blob [12] = bitlen [0]; // bitlen
+                       blob [13] = bitlen [1]; 
+                       blob [14] = bitlen [2]; 
+                       blob [15] = bitlen [3];
+
+                       // public exponent (DWORD)
+                       int pos = 16;
+                       int n = p.Exponent.Length;
+                       while (n > 0)
+                               blob [pos++] = p.Exponent [--n];
+                       // modulus
+                       pos = 20;
+                       byte[] part = p.Modulus;
+                       int len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+                       // private key
+                       part = p.P;
+                       len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+
+                       part = p.Q;
+                       len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+
+                       part = p.DP;
+                       len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+
+                       part = p.DQ;
+                       len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+
+                       part = p.InverseQ;
+                       len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+
+                       part = p.D;
+                       len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+
+                       return blob;
+               }
+
+               static public byte[] ToCapiPrivateKeyBlob (DSA dsa)
+               {
+                       DSAParameters p = dsa.ExportParameters (true);
+                       int keyLength = p.P.Length; // in bytes
+
+                       // header + P + Q + G + X + count + seed
+                       byte[] blob = new byte [16 + keyLength + 20 + keyLength + 20 + 4 + 20];
+
+                       blob [0] = 0x07;        // Type - PRIVATEKEYBLOB (0x07)
+                       blob [1] = 0x02;        // Version - Always CUR_BLOB_VERSION (0x02)
+                       // [2], [3]             // RESERVED - Always 0
+                       blob [5] = 0x22;        // ALGID
+                       blob [8] = 0x44;        // Magic
+                       blob [9] = 0x53;
+                       blob [10] = 0x53;
+                       blob [11] = 0x32;
+
+                       byte[] bitlen = GetBytesLE (keyLength << 3);
+                       blob [12] = bitlen [0];
+                       blob [13] = bitlen [1];
+                       blob [14] = bitlen [2];
+                       blob [15] = bitlen [3];
+
+                       int pos = 16;
+                       byte[] part = p.P;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+                       pos += keyLength;
+
+                       part = p.Q;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, 20);
+                       pos += 20;
+
+                       part = p.G;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+                       pos += keyLength;
+
+                       part = p.X;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, 20);
+                       pos += 20;
+
+                       Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4);
+                       pos += 4;
+
+                       part = p.Seed;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, 20);
+
+                       return blob;
+               }
+
+               static public RSA FromCapiPublicKeyBlob (byte[] blob) 
+               {
+                       return FromCapiPublicKeyBlob (blob, 0);
+               }
+
+               static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset) 
+               {
+                       if (blob == null)
+                               throw new ArgumentNullException ("blob");
+                       if (offset >= blob.Length)
+                               throw new ArgumentException ("blob is too small.");
+
+                       try {
+                               if ((blob [offset]   != 0x06) ||                                // PUBLICKEYBLOB (0x06)
+                                   (blob [offset+1] != 0x02) ||                                // Version (0x02)
+                                   (blob [offset+2] != 0x00) ||                                // Reserved (word)
+                                   (blob [offset+3] != 0x00) || 
+                                   (ToUInt32LE (blob, offset+8) != 0x31415352))        // DWORD magic = RSA1
+                                       throw new CryptographicException ("Invalid blob header");
+
+                               // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+                               // int algId = ToInt32LE (blob, offset+4);
+
+                               // DWORD bitlen
+                               int bitLen = ToInt32LE (blob, offset+12);
+
+                               // DWORD public exponent
+                               RSAParameters rsap = new RSAParameters ();
+                               rsap.Exponent = new byte [3];
+                               rsap.Exponent [0] = blob [offset+18];
+                               rsap.Exponent [1] = blob [offset+17];
+                               rsap.Exponent [2] = blob [offset+16];
+                       
+                               int pos = offset+20;
+                               // BYTE modulus[rsapubkey.bitlen/8];
+                               int byteLen = (bitLen >> 3);
+                               rsap.Modulus = new byte [byteLen];
+                               Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
+                               Array.Reverse (rsap.Modulus);
+
+                               RSA rsa = null;
+                               try {
+                                       rsa = RSA.Create ();
+                                       rsa.ImportParameters (rsap);
+                               }
+                               catch (CryptographicException) {
+                                       // this may cause problem when this code is run under
+                                       // the SYSTEM identity on Windows (e.g. ASP.NET). See
+                                       // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+                                       CspParameters csp = new CspParameters ();
+                                       csp.Flags = CspProviderFlags.UseMachineKeyStore;
+                                       rsa = new RSACryptoServiceProvider (csp);
+                                       rsa.ImportParameters (rsap);
+                               }
+                               return rsa;
+                       }
+                       catch (Exception e) {
+                               throw new CryptographicException ("Invalid blob.", e);
+                       }
+               }
+
+               static public DSA FromCapiPublicKeyBlobDSA (byte[] blob)
+               {
+                       return FromCapiPublicKeyBlobDSA (blob, 0);
+               }
+
+               static public DSA FromCapiPublicKeyBlobDSA (byte[] blob, int offset)
+               {
+                       if (blob == null)
+                               throw new ArgumentNullException ("blob");
+                       if (offset >= blob.Length)
+                               throw new ArgumentException ("blob is too small.");
+
+                       try {
+                               if ((blob [offset] != 0x06) ||                          // PUBLICKEYBLOB (0x06)
+                                   (blob [offset + 1] != 0x02) ||                      // Version (0x02)
+                                   (blob [offset + 2] != 0x00) ||                      // Reserved (word)
+                                   (blob [offset + 3] != 0x00) ||
+                                   (ToUInt32LE (blob, offset + 8) != 0x31535344))      // DWORD magic
+                                       throw new CryptographicException ("Invalid blob header");
+
+                               int bitlen = ToInt32LE (blob, offset + 12);
+                               DSAParameters dsap = new DSAParameters ();
+                               int bytelen = bitlen >> 3;
+                               int pos = offset + 16;
+
+                               dsap.P = new byte [bytelen];
+                               Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen);
+                               Array.Reverse (dsap.P);
+                               pos += bytelen;
+
+                               dsap.Q = new byte [20];
+                               Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20);
+                               Array.Reverse (dsap.Q);
+                               pos += 20;
+
+                               dsap.G = new byte [bytelen];
+                               Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen);
+                               Array.Reverse (dsap.G);
+                               pos += bytelen;
+
+                               dsap.Y = new byte [bytelen];
+                               Buffer.BlockCopy (blob, pos, dsap.Y, 0, bytelen);
+                               Array.Reverse (dsap.Y);
+                               pos += bytelen;
+
+                               dsap.Counter = ToInt32LE (blob, pos);
+                               pos += 4;
+
+                               dsap.Seed = new byte [20];
+                               Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20);
+                               Array.Reverse (dsap.Seed);
+                               pos += 20;
+
+                               DSA dsa = (DSA)DSA.Create ();
+                               dsa.ImportParameters (dsap);
+                               return dsa;
+                       }
+                       catch (Exception e) {
+                               throw new CryptographicException ("Invalid blob.", e);
+                       }
+               }
+
+               static public byte[] ToCapiPublicKeyBlob (RSA rsa) 
+               {
+                       RSAParameters p = rsa.ExportParameters (false);
+                       int keyLength = p.Modulus.Length; // in bytes
+                       byte[] blob = new byte [20 + keyLength];
+
+                       blob [0] = 0x06;        // Type - PUBLICKEYBLOB (0x06)
+                       blob [1] = 0x02;        // Version - Always CUR_BLOB_VERSION (0x02)
+                       // [2], [3]             // RESERVED - Always 0
+                       blob [5] = 0x24;        // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+                       blob [8] = 0x52;        // Magic - RSA1 (ASCII in hex)
+                       blob [9] = 0x53;
+                       blob [10] = 0x41;
+                       blob [11] = 0x31;
+
+                       byte[] bitlen = GetBytesLE (keyLength << 3);
+                       blob [12] = bitlen [0]; // bitlen
+                       blob [13] = bitlen [1]; 
+                       blob [14] = bitlen [2]; 
+                       blob [15] = bitlen [3];
+
+                       // public exponent (DWORD)
+                       int pos = 16;
+                       int n = p.Exponent.Length;
+                       while (n > 0)
+                               blob [pos++] = p.Exponent [--n];
+                       // modulus
+                       pos = 20;
+                       byte[] part = p.Modulus;
+                       int len = part.Length;
+                       Array.Reverse (part, 0, len);
+                       Buffer.BlockCopy (part, 0, blob, pos, len);
+                       pos += len;
+                       return blob;
+               }
+
+               static public byte[] ToCapiPublicKeyBlob (DSA dsa)
+               {
+                       DSAParameters p = dsa.ExportParameters (false);
+                       int keyLength = p.P.Length; // in bytes
+
+                       // header + P + Q + G + Y + count + seed
+                       byte[] blob = new byte [16 + keyLength + 20 + keyLength + keyLength + 4 + 20];
+
+                       blob [0] = 0x06;        // Type - PUBLICKEYBLOB (0x06)
+                       blob [1] = 0x02;        // Version - Always CUR_BLOB_VERSION (0x02)
+                       // [2], [3]             // RESERVED - Always 0
+                       blob [5] = 0x22;        // ALGID
+                       blob [8] = 0x44;        // Magic
+                       blob [9] = 0x53;
+                       blob [10] = 0x53;
+                       blob [11] = 0x31;
+
+                       byte[] bitlen = GetBytesLE (keyLength << 3);
+                       blob [12] = bitlen [0];
+                       blob [13] = bitlen [1];
+                       blob [14] = bitlen [2];
+                       blob [15] = bitlen [3];
+
+                       int pos = 16;
+                       byte[] part;
+
+                       part = p.P;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+                       pos += keyLength;
+
+                       part = p.Q;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, 20);
+                       pos += 20;
+
+                       part = p.G;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+                       pos += keyLength;
+
+                       part = p.Y;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+                       pos += keyLength;
+
+                       Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4);
+                       pos += 4;
+
+                       part = p.Seed;
+                       Array.Reverse (part);
+                       Buffer.BlockCopy (part, 0, blob, pos, 20);
+
+                       return blob;
+               }
+
+               // PRIVATEKEYBLOB
+               // PUBLICKEYBLOB
+               static public RSA FromCapiKeyBlob (byte[] blob) 
+               {
+                       return FromCapiKeyBlob (blob, 0);
+               }
+
+               static public RSA FromCapiKeyBlob (byte[] blob, int offset) 
+               {
+                       if (blob == null)
+                               throw new ArgumentNullException ("blob");
+                       if (offset >= blob.Length)
+                               throw new ArgumentException ("blob is too small.");
+
+                       switch (blob [offset]) {
+                               case 0x00:
+                                       // this could be a public key inside an header
+                                       // like "sn -e" would produce
+                                       if (blob [offset + 12] == 0x06) {
+                                               return FromCapiPublicKeyBlob (blob, offset + 12);
+                                       }
+                                       break;
+                               case 0x06:
+                                       return FromCapiPublicKeyBlob (blob, offset);
+                               case 0x07:
+                                       return FromCapiPrivateKeyBlob (blob, offset);
+                       }
+                       throw new CryptographicException ("Unknown blob format.");
+               }
+
+               static public DSA FromCapiKeyBlobDSA (byte[] blob)
+               {
+                       return FromCapiKeyBlobDSA (blob, 0);
+               }
+
+               static public DSA FromCapiKeyBlobDSA (byte[] blob, int offset)
+               {
+                       if (blob == null)
+                               throw new ArgumentNullException ("blob");
+                       if (offset >= blob.Length)
+                               throw new ArgumentException ("blob is too small.");
+
+                       switch (blob [offset]) {
+                               case 0x06:
+                                       return FromCapiPublicKeyBlobDSA (blob, offset);
+                               case 0x07:
+                                       return FromCapiPrivateKeyBlobDSA (blob, offset);
+                       }
+                       throw new CryptographicException ("Unknown blob format.");
+               }
+
+               static public byte[] ToCapiKeyBlob (AsymmetricAlgorithm keypair, bool includePrivateKey) 
+               {
+                       if (keypair == null)
+                               throw new ArgumentNullException ("keypair");
+
+                       // check between RSA and DSA (and potentially others like DH)
+                       if (keypair is RSA)
+                               return ToCapiKeyBlob ((RSA)keypair, includePrivateKey);
+                       else if (keypair is DSA)
+                               return ToCapiKeyBlob ((DSA)keypair, includePrivateKey);
+                       else
+                               return null;    // TODO
+               }
+
+               static public byte[] ToCapiKeyBlob (RSA rsa, bool includePrivateKey) 
+               {
+                       if (rsa == null)
+                               throw new ArgumentNullException ("rsa");
+
+                       if (includePrivateKey)
+                               return ToCapiPrivateKeyBlob (rsa);
+                       else
+                               return ToCapiPublicKeyBlob (rsa);
+               }
+
+               static public byte[] ToCapiKeyBlob (DSA dsa, bool includePrivateKey)
+               {
+                       if (dsa == null)
+                               throw new ArgumentNullException ("dsa");
+
+                       if (includePrivateKey)
+                               return ToCapiPrivateKeyBlob (dsa);
+                       else
+                               return ToCapiPublicKeyBlob (dsa);
+               }
+
+               static public string ToHex (byte[] input) 
+               {
+                       if (input == null)
+                               return null;
+
+                       StringBuilder sb = new StringBuilder (input.Length * 2);
+                       foreach (byte b in input) {
+                               sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
+                       }
+                       return sb.ToString ();
+               }
+
+               static private byte FromHexChar (char c) 
+               {
+                       if ((c >= 'a') && (c <= 'f'))
+                               return (byte) (c - 'a' + 10);
+                       if ((c >= 'A') && (c <= 'F'))
+                               return (byte) (c - 'A' + 10);
+                       if ((c >= '0') && (c <= '9'))
+                               return (byte) (c - '0');
+                       throw new ArgumentException ("invalid hex char");
+               }
+
+               static public byte[] FromHex (string hex) 
+               {
+                       if (hex == null)
+                               return null;
+                       if ((hex.Length & 0x1) == 0x1)
+                               throw new ArgumentException ("Length must be a multiple of 2");
+
+                       byte[] result = new byte [hex.Length >> 1];
+                       int n = 0;
+                       int i = 0;
+                       while (n < result.Length) {
+                               result [n] = (byte) (FromHexChar (hex [i++]) << 4);
+                               result [n++] += FromHexChar (hex [i++]);
+                       }
+                       return result;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Impl/CryptoHack.cs b/mcs/class/IKVM.Reflection/Impl/CryptoHack.cs
new file mode 100644 (file)
index 0000000..1a8b46a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Security.Cryptography;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection.Impl
+{
+       static class CryptoHack
+       {
+               internal static RSA CreateRSA(StrongNameKeyPair keyPair)
+               {
+                       // HACK use serialization to get at the private key or key container name,
+                       // this should be more future proof than using reflection to access the fields directly.
+                       SerializationInfo ser = new SerializationInfo(typeof(StrongNameKeyPair), new FormatterConverter());
+                       ((ISerializable)keyPair.keyPair).GetObjectData(ser, new StreamingContext());
+                       byte[] key = (byte[])ser.GetValue("_keyPairArray", typeof(byte[]));
+                       string keycontainer = ser.GetString("_keyPairContainer");
+                       if (keycontainer != null)
+                       {
+                               CspParameters parm = new CspParameters();
+                               parm.Flags = CspProviderFlags.UseMachineKeyStore;
+                               parm.KeyContainerName = keycontainer;
+                               parm.KeyNumber = 2;     // Signature
+                               return new RSACryptoServiceProvider(parm);
+                       }
+                       else
+                       {
+                               return Mono.Security.Cryptography.CryptoConvert.FromCapiKeyBlob(key);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Impl/ITypeOwner.cs b/mcs/class/IKVM.Reflection/Impl/ITypeOwner.cs
new file mode 100644 (file)
index 0000000..10050f7
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+       interface ITypeOwner
+       {
+               ModuleBuilder ModuleBuilder { get; }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Impl/MdbWriter.cs b/mcs/class/IKVM.Reflection/Impl/MdbWriter.cs
new file mode 100644 (file)
index 0000000..06d3ed0
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+#if MONO
+using System;
+using System.Collections.Generic;
+using Mono.CompilerServices.SymbolWriter;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+       sealed class Method : IMethodDef
+       {
+               internal int token;
+               internal string name;
+               internal SymbolDocumentWriter document;
+               internal int[] offsets;
+               internal int[] lines;
+               internal int[] columns;
+               internal List<string> variables = new List<string>();
+
+               public string Name
+               {
+                       get { return name; }
+               }
+
+               public int Token
+               {
+                       get { return token; }
+               }
+       }
+
+       sealed class SymbolDocumentWriter : System.Diagnostics.SymbolStore.ISymbolDocumentWriter
+       {
+               internal readonly string url;
+               internal SourceFileEntry source;
+
+               internal SymbolDocumentWriter(string url)
+               {
+                       this.url = url;
+               }
+
+               public void SetCheckSum(Guid algorithmId, byte[] checkSum)
+               {
+               }
+
+               public void SetSource(byte[] source)
+               {
+               }
+       }
+
+       sealed class MdbWriter : ISymbolWriterImpl
+       {
+               private readonly ModuleBuilder moduleBuilder;
+               private readonly Dictionary<int, Method> methods = new Dictionary<int, Method>();
+               private readonly Dictionary<string, SymbolDocumentWriter> documents = new Dictionary<string, SymbolDocumentWriter>();
+               private Method currentMethod;
+
+               internal MdbWriter(ModuleBuilder moduleBuilder)
+               {
+                       this.moduleBuilder = moduleBuilder;
+               }
+
+               public byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd)
+               {
+                       return Empty<byte>.Array;
+               }
+
+               public void RemapToken(int oldToken, int newToken)
+               {
+                       if (methods.ContainsKey(oldToken))
+                       {
+                               methods[oldToken].token = newToken;
+                       }
+               }
+
+               public void Close()
+               {
+                       MonoSymbolWriter writer = new MonoSymbolWriter(moduleBuilder.FullyQualifiedName);
+
+                       foreach (Method method in methods.Values)
+                       {
+                               if (method.document != null)
+                               {
+                                       if (method.document.source == null)
+                                       {
+                                               method.document.source = new SourceFileEntry(writer.SymbolFile, method.document.url);
+                                       }
+                                       ICompileUnit file = new CompileUnitEntry(writer.SymbolFile, method.document.source);
+                                       SourceMethodBuilder smb = writer.OpenMethod(file, 0, method);
+                                       for (int i = 0; i < method.offsets.Length; i++)
+                                       {
+                                               smb.MarkSequencePoint(method.offsets[i], method.document.source, method.lines[i], method.columns[i], false);
+                                       }
+                                       for (int i = 0; i < method.variables.Count; i++)
+                                       {
+                                               writer.DefineLocalVariable(i, method.variables[i]);
+                                       }
+                                       writer.CloseMethod();
+                               }
+                       }
+
+                       writer.WriteSymbolFile(moduleBuilder.ModuleVersionId);
+               }
+
+               public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
+               {
+                       SymbolDocumentWriter writer;
+                       if (!documents.TryGetValue(url, out writer))
+                       {
+                               writer = new SymbolDocumentWriter(url);
+                               documents.Add(url, writer);
+                       }
+                       return writer;
+               }
+
+               public void OpenMethod(System.Diagnostics.SymbolStore.SymbolToken token)
+               {
+                       Method method = new Method();
+                       method.token = token.GetToken();
+                       // name doesn't appear to be used. We can look it up, but ModuleBuilder.ResolveMethod() is inefficient,
+                       // so if it isn't used, why bother?
+                       method.name = null; // moduleBuilder.ResolveMethod(token.GetToken()).Name;
+                       methods.Add(token.GetToken(), method);
+                       currentMethod = method;
+               }
+
+               public void CloseMethod()
+               {
+                       currentMethod = null;
+               }
+
+               public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+               {
+               }
+
+               public void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+               {
+                       currentMethod.variables.Add(name);
+               }
+
+               public void DefineSequencePoints(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)
+               {
+                       currentMethod.document = (SymbolDocumentWriter)document;
+                       currentMethod.offsets = offsets;
+                       currentMethod.lines = lines;
+                       currentMethod.columns = columns;
+               }
+
+               public void DefineParameter(string name, System.Reflection.ParameterAttributes attributes, int sequence, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3)
+               {
+               }
+
+               public void DefineField(System.Diagnostics.SymbolStore.SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3)
+               {
+               }
+
+               public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3)
+               {
+               }
+
+               public void OpenNamespace(string name)
+               {
+               }
+
+               public void CloseNamespace()
+               {
+               }
+
+               public void UsingNamespace(string fullName)
+               {
+               }
+
+               public int OpenScope(int startOffset)
+               {
+                       return 0;
+               }
+
+               public void CloseScope(int endOffset)
+               {
+               }
+
+               public void SetMethodSourceRange(System.Diagnostics.SymbolStore.ISymbolDocumentWriter startDoc, int startLine, int startColumn, System.Diagnostics.SymbolStore.ISymbolDocumentWriter endDoc, int endLine, int endColumn)
+               {
+               }
+
+               public void SetScopeRange(int scopeID, int startOffset, int endOffset)
+               {
+               }
+
+               public void SetSymAttribute(System.Diagnostics.SymbolStore.SymbolToken parent, string name, byte[] data)
+               {
+               }
+
+               public void SetUserEntryPoint(System.Diagnostics.SymbolStore.SymbolToken entryMethod)
+               {
+               }
+
+               public void SetUnderlyingWriter(IntPtr underlyingWriter)
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public void Initialize(IntPtr emitter, string filename, bool fFullBuild)
+               {
+                       throw new InvalidOperationException();
+               }
+       }
+}
+#endif // MONO
diff --git a/mcs/class/IKVM.Reflection/Impl/PdbWriter.cs b/mcs/class/IKVM.Reflection/Impl/PdbWriter.cs
new file mode 100644 (file)
index 0000000..aacc6c9
--- /dev/null
@@ -0,0 +1,1180 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Diagnostics.SymbolStore;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+       [Guid("7dac8207-d3ae-4c75-9b67-92801a497d44")]
+       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+       [ComImport]
+       interface IMetaDataImport
+       {
+               void PlaceHolder_CloseEnum();
+               void PlaceHolder_CountEnum();
+               void PlaceHolder_ResetEnum();
+               void PlaceHolder_EnumTypeDefs();
+               void PlaceHolder_EnumInterfaceImpls();
+               void PlaceHolder_EnumTypeRefs();
+               void PlaceHolder_FindTypeDefByName();
+               void PlaceHolder_GetScopeProps();
+               void PlaceHolder_GetModuleFromScope();
+
+               void GetTypeDefProps(
+                       int                     td,                     // [IN] TypeDef token for inquiry.
+               IntPtr          szTypeDef,              // [OUT] Put name here.
+                   int                 cchTypeDef,             // [IN] size of name buffer in wide chars.
+                       IntPtr          pchTypeDef,                             // [OUT] put size of name (wide chars) here.
+                       IntPtr          pdwTypeDefFlags,                // [OUT] Put flags here.
+                       IntPtr          ptkExtends);                    // [OUT] Put base class TypeDef/TypeRef here.
+
+               void PlaceHolder_GetInterfaceImplProps();
+               void PlaceHolder_GetTypeRefProps();
+               void PlaceHolder_ResolveTypeRef();
+               void PlaceHolder_EnumMembers();
+               void PlaceHolder_EnumMembersWithName();
+               void PlaceHolder_EnumMethods();
+               void PlaceHolder_EnumMethodsWithName();
+               void PlaceHolder_EnumFields();
+               void PlaceHolder_EnumFieldsWithName();
+               void PlaceHolder_EnumParams();
+               void PlaceHolder_EnumMemberRefs();
+               void PlaceHolder_EnumMethodImpls();
+               void PlaceHolder_EnumPermissionSets();
+               void PlaceHolder_FindMember();
+               void PlaceHolder_FindMethod();
+               void PlaceHolder_FindField();
+               void PlaceHolder_FindMemberRef();
+
+               void GetMethodProps(
+                       int                     mb,                     // The method for which to get props.   
+                       IntPtr          pClass,                                 // Put method's class here. 
+                       IntPtr      szMethod,               // Put method's name here.  
+                       int                     cchMethod,              // Size of szMethod buffer in wide chars.   
+                       IntPtr      pchMethod,                          // Put actual size here 
+                       IntPtr          pdwAttr,                                // Put flags here.  
+                       IntPtr          ppvSigBlob,                             // [OUT] point to the blob value of meta data   
+                       IntPtr          pcbSigBlob,                             // [OUT] actual size of signature blob  
+                       IntPtr          pulCodeRVA,                             // [OUT] codeRVA    
+                       IntPtr          pdwImplFlags);              // [OUT] Impl. Flags    
+
+               void PlaceHolder_GetMemberRefProps();
+               void PlaceHolder_EnumProperties();
+               void PlaceHolder_EnumEvents();
+               void PlaceHolder_GetEventProps();
+               void PlaceHolder_EnumMethodSemantics();
+               void PlaceHolder_GetMethodSemantics();
+               void PlaceHolder_GetClassLayout();
+               void PlaceHolder_GetFieldMarshal();
+               void PlaceHolder_GetRVA();
+               void PlaceHolder_GetPermissionSetProps();
+               void PlaceHolder_GetSigFromToken();
+               void PlaceHolder_GetModuleRefProps();
+               void PlaceHolder_EnumModuleRefs();
+               void PlaceHolder_GetTypeSpecFromToken();
+               void PlaceHolder_GetNameFromToken();
+               void PlaceHolder_EnumUnresolvedMethods();
+               void PlaceHolder_GetUserString();
+               void PlaceHolder_GetPinvokeMap();
+               void PlaceHolder_EnumSignatures();
+               void PlaceHolder_EnumTypeSpecs();
+               void PlaceHolder_EnumUserStrings();
+               void PlaceHolder_GetParamForMethodIndex();
+               void PlaceHolder_EnumCustomAttributes();
+               void PlaceHolder_GetCustomAttributeProps();
+               void PlaceHolder_FindTypeRef();
+               void PlaceHolder_GetMemberProps();
+               void PlaceHolder_GetFieldProps();
+               void PlaceHolder_GetPropertyProps();
+               void PlaceHolder_GetParamProps();
+               void PlaceHolder_GetCustomAttributeByName();
+               void PlaceHolder_IsValidToken();
+
+               void GetNestedClassProps(
+                       int             tdNestedClass,                  // [IN] NestedClass token.
+                       IntPtr  ptdEnclosingClass);             // [OUT] EnclosingClass token.
+
+               void PlaceHolder_GetNativeCallConvFromSig();
+               void PlaceHolder_IsGlobal();
+       }
+
+       [Guid("ba3fee4c-ecb9-4e41-83b7-183fa41cd859")]
+       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+       [ComImport]
+       interface IMetaDataEmit
+       {
+               void PlaceHolder_SetModuleProps();
+               void PlaceHolder_Save();
+               void PlaceHolder_SaveToStream();
+               void PlaceHolder_GetSaveSize();
+               void PlaceHolder_DefineTypeDef();
+               void PlaceHolder_DefineNestedType();
+               void PlaceHolder_SetHandler();
+               void PlaceHolder_DefineMethod();
+               void PlaceHolder_DefineMethodImpl();
+               void PlaceHolder_DefineTypeRefByName();
+               void PlaceHolder_DefineImportType();
+               void PlaceHolder_DefineMemberRef();
+               void PlaceHolder_DefineImportMember();
+               void PlaceHolder_DefineEvent();
+               void PlaceHolder_SetClassLayout();
+               void PlaceHolder_DeleteClassLayout();
+               void PlaceHolder_SetFieldMarshal();
+               void PlaceHolder_DeleteFieldMarshal();
+               void PlaceHolder_DefinePermissionSet();
+               void PlaceHolder_SetRVA();
+               void PlaceHolder_GetTokenFromSig();
+               void PlaceHolder_DefineModuleRef();
+               void PlaceHolder_SetParent();
+               void PlaceHolder_GetTokenFromTypeSpec();
+               void PlaceHolder_SaveToMemory();
+               void PlaceHolder_DefineUserString();
+               void PlaceHolder_DeleteToken();
+               void PlaceHolder_SetMethodProps();
+               void PlaceHolder_SetTypeDefProps();
+               void PlaceHolder_SetEventProps();
+               void PlaceHolder_SetPermissionSetProps();
+               void PlaceHolder_DefinePinvokeMap();
+               void PlaceHolder_SetPinvokeMap();
+               void PlaceHolder_DeletePinvokeMap();
+               void PlaceHolder_DefineCustomAttribute();
+               void PlaceHolder_SetCustomAttributeValue();
+               void PlaceHolder_DefineField();
+               void PlaceHolder_DefineProperty();
+               void PlaceHolder_DefineParam();
+               void PlaceHolder_SetFieldProps();
+               void PlaceHolder_SetPropertyProps();
+               void PlaceHolder_SetParamProps();
+               void PlaceHolder_DefineSecurityAttributeSet();
+               void PlaceHolder_ApplyEditAndContinue();
+               void PlaceHolder_TranslateSigWithScope();
+               void PlaceHolder_SetMethodImplFlags();
+               void PlaceHolder_SetFieldRVA();
+               void PlaceHolder_Merge();
+               void PlaceHolder_MergeEnd();
+       }
+
+       [Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006")]
+       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+       [ComImport]
+       internal interface ISymUnmanagedDocumentWriter { }
+
+       [Guid("0b97726e-9e6d-4f05-9a26-424022093caa")]
+       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+       [ComImport]
+       [CoClass(typeof(CorSymWriterClass))]
+       interface ISymUnmanagedWriter2
+       {
+               ISymUnmanagedDocumentWriter DefineDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType);
+               void PlaceHolder_SetUserEntryPoint();
+               void OpenMethod(int method);
+               void CloseMethod();
+               int OpenScope(int startOffset);
+               void CloseScope(int endOffset);
+               void PlaceHolder_SetScopeRange();
+               void DefineLocalVariable(string name, int attributes, int cSig, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, int addrKind, int addr1, int addr2, int startOffset, int endOffset);
+               void PlaceHolder_DefineParameter();
+               void PlaceHolder_DefineField();
+               void PlaceHolder_DefineGlobalVariable();
+               void Close();
+               void PlaceHolder_SetSymAttribute();
+               void PlaceHolder_OpenNamespace();
+               void PlaceHolder_CloseNamespace();
+               void PlaceHolder_UsingNamespace();
+               void PlaceHolder_SetMethodSourceRange();
+               void Initialize([MarshalAs(UnmanagedType.IUnknown)] object emitter, string filename, [MarshalAs(UnmanagedType.IUnknown)] object pIStream, bool fFullBuild);
+
+               void GetDebugInfo(
+                       [In, Out] ref IMAGE_DEBUG_DIRECTORY pIDD,
+                       [In]  uint cData,
+                       [Out] out uint pcData,
+                       [Out, MarshalAs(UnmanagedType.LPArray)] byte[] data);
+
+               void DefineSequencePoints(ISymUnmanagedDocumentWriter document, int spCount,
+                 [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets,
+                 [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines,
+                 [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns,
+                 [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines,
+                 [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns);
+
+               void RemapToken(
+                       [In] int oldToken,
+                       [In] int newToken);
+
+               void PlaceHolder_Initialize2();
+               void PlaceHolder_DefineConstant();
+               void PlaceHolder_Abort();
+
+               void DefineLocalVariable2(string name, int attributes, int token, int addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset);
+
+               void PlaceHolder_DefineGlobalVariable2();
+               void PlaceHolder_DefineConstant2();
+       }
+
+       [Guid("108296c1-281e-11d3-bd22-0000f80849bd")]
+       [ComImport]
+       class CorSymWriterClass { }
+
+       sealed class PdbWriter : ISymbolWriterImpl, IMetaDataEmit, IMetaDataImport
+       {
+               private readonly ModuleBuilder moduleBuilder;
+               private ISymUnmanagedWriter2 symUnmanagedWriter;
+               private readonly Dictionary<string, Document> documents = new Dictionary<string, Document>();
+               private readonly List<Method> methods = new List<Method>();
+               private readonly Dictionary<int, int> remap = new Dictionary<int, int>();
+               private readonly Dictionary<int, int> reversemap = new Dictionary<int, int>();
+               private Method currentMethod;
+
+               internal PdbWriter(ModuleBuilder moduleBuilder)
+               {
+                       this.moduleBuilder = moduleBuilder;
+               }
+
+               private sealed class Document : ISymbolDocumentWriter
+               {
+                       internal readonly string url;
+                       private Guid language;
+                       private Guid languageVendor;
+                       private Guid documentType;
+                       private ISymUnmanagedDocumentWriter unmanagedDocument;
+
+                       internal Document(string url, Guid language, Guid languageVendor, Guid documentType)
+                       {
+                               this.url = url;
+                               this.language = language;
+                               this.languageVendor = languageVendor;
+                               this.documentType = documentType;
+                       }
+
+                       public void SetCheckSum(Guid algorithmId, byte[] checkSum)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public void SetSource(byte[] source)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       internal ISymUnmanagedDocumentWriter GetUnmanagedDocument(ISymUnmanagedWriter2 symUnmanagedWriter)
+                       {
+                               if (unmanagedDocument == null)
+                               {
+                                       unmanagedDocument = symUnmanagedWriter.DefineDocument(url, ref language, ref languageVendor, ref documentType);
+                               }
+                               return unmanagedDocument;
+                       }
+
+                       internal void Release()
+                       {
+                               if (unmanagedDocument != null)
+                               {
+                                       Marshal.ReleaseComObject(unmanagedDocument);
+                                       unmanagedDocument = null;
+                               }
+                       }
+               }
+
+               private sealed class LocalVar
+               {
+                       internal readonly FieldAttributes attributes;
+                       internal readonly int signature;
+                       internal readonly SymAddressKind addrKind;
+                       internal readonly int addr1;
+                       internal readonly int addr2;
+                       internal readonly int addr3;
+                       internal readonly int startOffset;
+                       internal readonly int endOffset;
+
+                       internal LocalVar(FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+                       {
+                               this.attributes = attributes;
+                               this.signature = signature;
+                               this.addrKind = addrKind;
+                               this.addr1 = addr1;
+                               this.addr2 = addr2;
+                               this.addr3 = addr3;
+                               this.startOffset = startOffset;
+                               this.endOffset = endOffset;
+                       }
+               }
+
+               private sealed class Scope
+               {
+                       internal readonly int startOffset;
+                       internal int endOffset;
+                       internal readonly List<Scope> scopes = new List<Scope>();
+                       internal readonly Dictionary<string, LocalVar> locals = new Dictionary<string, LocalVar>();
+
+                       internal Scope(int startOffset)
+                       {
+                               this.startOffset = startOffset;
+                       }
+
+                       internal void Do(ISymUnmanagedWriter2 symUnmanagedWriter)
+                       {
+                               symUnmanagedWriter.OpenScope(startOffset);
+                               foreach (KeyValuePair<string, LocalVar> kv in locals)
+                               {
+                                       symUnmanagedWriter.DefineLocalVariable2(kv.Key, (int)kv.Value.attributes, kv.Value.signature, (int)kv.Value.addrKind, kv.Value.addr1, kv.Value.addr2, kv.Value.addr3, kv.Value.startOffset, kv.Value.endOffset);
+                               }
+                               foreach (Scope scope in scopes)
+                               {
+                                       scope.Do(symUnmanagedWriter);
+                               }
+                               symUnmanagedWriter.CloseScope(endOffset);
+                       }
+               }
+
+               private sealed class Method
+               {
+                       internal readonly int token;
+                       internal Document document;
+                       internal int[] offsets;
+                       internal int[] lines;
+                       internal int[] columns;
+                       internal int[] endLines;
+                       internal int[] endColumns;
+                       internal readonly List<Scope> scopes = new List<Scope>();
+                       internal readonly Stack<Scope> scopeStack = new Stack<Scope>();
+
+                       internal Method(int token)
+                       {
+                               this.token = token;
+                       }
+               }
+
+               public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
+               {
+                       Document doc;
+                       if (!documents.TryGetValue(url, out doc))
+                       {
+                               doc = new Document(url, language, languageVendor, documentType);
+                               documents.Add(url, doc);
+                       }
+                       return doc;
+               }
+
+               public void OpenMethod(SymbolToken method)
+               {
+                       currentMethod = new Method(method.GetToken());
+               }
+
+               public void CloseMethod()
+               {
+                       methods.Add(currentMethod);
+                       currentMethod = null;
+               }
+
+               public void DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)
+               {
+                       currentMethod.document = (Document)document;
+                       currentMethod.offsets = offsets;
+                       currentMethod.lines = lines;
+                       currentMethod.columns = columns;
+                       currentMethod.endLines = endLines;
+                       currentMethod.endColumns = endColumns;
+               }
+
+               public int OpenScope(int startOffset)
+               {
+                       Scope scope = new Scope(startOffset);
+                       if (currentMethod.scopeStack.Count == 0)
+                       {
+                               currentMethod.scopes.Add(scope);
+                       }
+                       else
+                       {
+                               currentMethod.scopeStack.Peek().scopes.Add(scope);
+                       }
+                       currentMethod.scopeStack.Push(scope);
+                       return 0;
+               }
+
+               public void CloseScope(int endOffset)
+               {
+                       currentMethod.scopeStack.Pop().endOffset = endOffset;
+               }
+
+               public void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+               {
+                       currentMethod.scopeStack.Peek().locals[name] = new LocalVar(attributes, signature, addrKind, addr1, addr2, addr3, startOffset, endOffset);
+               }
+
+               private void InitWriter()
+               {
+                       if (symUnmanagedWriter == null)
+                       {
+                               string fileName = System.IO.Path.ChangeExtension(moduleBuilder.FullyQualifiedName, ".pdb");
+                               // pro-actively delete the .pdb to get a meaningful IOException, instead of COMInteropException if the file can't be overwritten (or is corrupt, or who knows what)
+                               System.IO.File.Delete(fileName);
+                               symUnmanagedWriter = new ISymUnmanagedWriter2();
+                               symUnmanagedWriter.Initialize(this, fileName, null, true);
+                       }
+               }
+
+               public byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd)
+               {
+                       InitWriter();
+                       uint cData;
+                       symUnmanagedWriter.GetDebugInfo(ref idd, 0, out cData, null);
+                       byte[] buf = new byte[cData];
+                       symUnmanagedWriter.GetDebugInfo(ref idd, (uint)buf.Length, out cData, buf);
+                       return buf;
+               }
+
+               public void RemapToken(int oldToken, int newToken)
+               {
+                       remap.Add(oldToken, newToken);
+                       reversemap.Add(newToken, oldToken);
+               }
+
+               public void Close()
+               {
+                       InitWriter();
+
+                       foreach (Method method in methods)
+                       {
+                               int remappedToken = method.token;
+                               remap.TryGetValue(remappedToken, out remappedToken);
+                               symUnmanagedWriter.OpenMethod(remappedToken);
+                               if (method.document != null)
+                               {
+                                       ISymUnmanagedDocumentWriter doc = method.document.GetUnmanagedDocument(symUnmanagedWriter);
+                                       symUnmanagedWriter.DefineSequencePoints(doc, method.offsets.Length, method.offsets, method.lines, method.columns, method.endLines, method.endColumns);
+                               }
+                               foreach (Scope scope in method.scopes)
+                               {
+                                       scope.Do(symUnmanagedWriter);
+                               }
+                               symUnmanagedWriter.CloseMethod(); 
+                       }
+
+                       foreach (Document doc in documents.Values)
+                       {
+                               doc.Release();
+                       }
+
+                       symUnmanagedWriter.Close();
+                       Marshal.ReleaseComObject(symUnmanagedWriter);
+                       symUnmanagedWriter = null;
+                       documents.Clear();
+                       methods.Clear();
+                       remap.Clear();
+                       reversemap.Clear();
+               }
+
+               public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void CloseNamespace()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void DefineField(SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void DefineParameter(string name, System.Reflection.ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Initialize(IntPtr emitter, string filename, bool fFullBuild)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void OpenNamespace(string name)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void SetMethodSourceRange(ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void SetScopeRange(int scopeID, int startOffset, int endOffset)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void SetSymAttribute(SymbolToken parent, string name, byte[] data)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void SetUnderlyingWriter(IntPtr underlyingWriter)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void SetUserEntryPoint(SymbolToken entryMethod)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void UsingNamespace(string fullName)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_CloseEnum()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_CountEnum()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_ResetEnum()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumTypeDefs()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumInterfaceImpls()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumTypeRefs()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_FindTypeDefByName()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetScopeProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetModuleFromScope()
+               {
+                       throw new NotImplementedException();
+               }
+
+               private static void WriteString(IntPtr ptrString, IntPtr ptrLength, string str, int length)
+               {
+                       if (ptrString != IntPtr.Zero)
+                       {
+                               for (int i = 0; i < Math.Min(length, str.Length); i++)
+                               {
+                                       Marshal.WriteInt16(ptrString, i, str[i]);
+                               }
+                       }
+                       if (ptrLength != IntPtr.Zero)
+                       {
+                               Marshal.WriteInt32(ptrLength, str.Length);
+                       }
+               }
+
+               private static void WriteToken(IntPtr ptr, MemberInfo member)
+               {
+                       if (ptr != IntPtr.Zero)
+                       {
+                               Marshal.WriteInt32(ptr, member == null ? 0 : member.MetadataToken);
+                       }
+               }
+
+               private static void WriteInt32(IntPtr ptr, int value)
+               {
+                       if (ptr != IntPtr.Zero)
+                       {
+                               Marshal.WriteInt32(ptr, value);
+                       }
+               }
+
+               public void GetTypeDefProps(
+                       int td,                     // [IN] TypeDef token for inquiry.
+                       IntPtr szTypeDef,                       // [OUT] Put name here.
+                       int cchTypeDef,             // [IN] size of name buffer in wide chars.
+                       IntPtr pchTypeDef,                      // [OUT] put size of name (wide chars) here.
+                       IntPtr pdwTypeDefFlags,         // [OUT] Put flags here.
+                       IntPtr ptkExtends)                      // [OUT] Put base class TypeDef/TypeRef here.
+               {
+                       if (td == 0)
+                       {
+                               // why are we being called with an invalid token?
+                               WriteString(szTypeDef, pchTypeDef, "", cchTypeDef);
+                               WriteInt32(pdwTypeDefFlags, 0);
+                               WriteToken(ptkExtends, null);
+                       }
+                       else
+                       {
+                               Type type = moduleBuilder.ResolveType(td);
+                               WriteString(szTypeDef, pchTypeDef, type.FullName, cchTypeDef);
+                               WriteInt32(pdwTypeDefFlags, (int)type.Attributes);
+                               WriteToken(ptkExtends, type.BaseType);
+                       }
+               }
+
+               public void PlaceHolder_GetInterfaceImplProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetTypeRefProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_ResolveTypeRef()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMembers()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMembersWithName()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMethods()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMethodsWithName()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumFields()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumFieldsWithName()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumParams()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMemberRefs()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMethodImpls()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumPermissionSets()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_FindMember()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_FindMethod()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_FindField()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_FindMemberRef()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void GetMethodProps(
+                       int mb,                                         // The method for which to get props.   
+                       IntPtr pClass,                          // [OUT] Put method's class here. 
+                       IntPtr szMethod,            // [OUT] Put method's name here.  
+                       int cchMethod,              // Size of szMethod buffer in wide chars.   
+                       IntPtr pchMethod,                       // [OUT] Put actual size here 
+                       IntPtr pdwAttr,                         // [OUT] Put flags here.  
+                       IntPtr ppvSigBlob,                      // [OUT] point to the blob value of meta data   
+                       IntPtr pcbSigBlob,                      // [OUT] actual size of signature blob  
+                       IntPtr pulCodeRVA,                      // [OUT] codeRVA    
+                       IntPtr pdwImplFlags)            // [OUT] Impl. Flags    
+               {
+                       if (pdwAttr != IntPtr.Zero || ppvSigBlob != IntPtr.Zero || pcbSigBlob != IntPtr.Zero || pulCodeRVA != IntPtr.Zero || pdwImplFlags != IntPtr.Zero)
+                       {
+                               throw new NotImplementedException();
+                       }
+                       MethodBase method = moduleBuilder.ResolveMethod(reversemap[mb]);
+                       WriteToken(pClass, method.DeclaringType);
+                       WriteString(szMethod, pchMethod, method.Name, cchMethod);
+               }
+
+               public void PlaceHolder_GetMemberRefProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumProperties()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumEvents()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetEventProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumMethodSemantics()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetMethodSemantics()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetClassLayout()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetFieldMarshal()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetRVA()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetPermissionSetProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetSigFromToken()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetModuleRefProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumModuleRefs()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetTypeSpecFromToken()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetNameFromToken()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumUnresolvedMethods()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetUserString()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetPinvokeMap()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumSignatures()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumTypeSpecs()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumUserStrings()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetParamForMethodIndex()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_EnumCustomAttributes()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetCustomAttributeProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_FindTypeRef()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetMemberProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetFieldProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetPropertyProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetParamProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetCustomAttributeByName()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_IsValidToken()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void GetNestedClassProps(
+                       int tdNestedClass,                              // [IN] NestedClass token.
+                       IntPtr ptdEnclosingClass)               // [OUT] EnclosingClass token.
+               {
+                       Type type = moduleBuilder.ResolveType(tdNestedClass);
+                       WriteToken(ptdEnclosingClass, type.DeclaringType);
+               }
+
+               public void PlaceHolder_GetNativeCallConvFromSig()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_IsGlobal()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetModuleProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_Save()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SaveToStream()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetSaveSize()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineTypeDef()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineNestedType()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetHandler()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineMethod()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineMethodImpl()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineTypeRefByName()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineImportType()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineMemberRef()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineImportMember()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineEvent()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetClassLayout()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DeleteClassLayout()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetFieldMarshal()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DeleteFieldMarshal()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefinePermissionSet()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetRVA()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetTokenFromSig()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineModuleRef()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetParent()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_GetTokenFromTypeSpec()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SaveToMemory()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineUserString()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DeleteToken()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetMethodProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetTypeDefProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetEventProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetPermissionSetProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefinePinvokeMap()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetPinvokeMap()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DeletePinvokeMap()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineCustomAttribute()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetCustomAttributeValue()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineField()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineProperty()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineParam()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetFieldProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetPropertyProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetParamProps()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_DefineSecurityAttributeSet()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_ApplyEditAndContinue()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_TranslateSigWithScope()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetMethodImplFlags()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_SetFieldRVA()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_Merge()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void PlaceHolder_MergeEnd()
+               {
+                       throw new NotImplementedException();
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Impl/SymbolSupport.cs b/mcs/class/IKVM.Reflection/Impl/SymbolSupport.cs
new file mode 100644 (file)
index 0000000..945187e
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2008, 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics.SymbolStore;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+       [StructLayout(LayoutKind.Sequential)]
+       struct IMAGE_DEBUG_DIRECTORY
+       {
+               public uint Characteristics;
+               public uint TimeDateStamp;
+               public ushort MajorVersion;
+               public ushort MinorVersion;
+               public uint Type;
+               public uint SizeOfData;
+               public uint AddressOfRawData;
+               public uint PointerToRawData;
+       }
+
+       interface ISymbolWriterImpl : ISymbolWriter
+       {
+               byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd);
+               void RemapToken(int oldToken, int newToken);
+               void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset);
+       }
+
+       static class SymbolSupport
+       {
+               private static readonly bool runningOnMono = System.Type.GetType("Mono.Runtime") != null;
+
+               internal static ISymbolWriterImpl CreateSymbolWriterFor(ModuleBuilder moduleBuilder)
+               {
+#if !NO_SYMBOL_WRITER
+                       throw new NotSupportedException ("IKVM.Reflection with no symbol writer support");
+#else
+                       if (runningOnMono)
+                       {
+#if MONO
+                               return new MdbWriter(moduleBuilder);
+#else
+                               throw new NotSupportedException("IKVM.Reflection must be compiled with MONO defined to support writing Mono debugging symbols.");
+#endif
+                       }
+                       else
+                       {
+                               return new PdbWriter(moduleBuilder);
+                       }
+#endif
+               }
+
+               internal static byte[] GetDebugInfo(ISymbolWriterImpl writer, ref IMAGE_DEBUG_DIRECTORY idd)
+               {
+                       return writer.GetDebugInfo(ref idd);
+               }
+
+               internal static void RemapToken(ISymbolWriterImpl writer, int oldToken, int newToken)
+               {
+                       writer.RemapToken(oldToken, newToken);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/InterfaceMapping.cs b/mcs/class/IKVM.Reflection/InterfaceMapping.cs
new file mode 100644 (file)
index 0000000..f589cfe
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+       public struct InterfaceMapping
+       {
+               public MethodInfo[] InterfaceMethods;
+               public Type InterfaceType;
+               public MethodInfo[] TargetMethods;
+               public Type TargetType;
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/LocalVariableInfo.cs b/mcs/class/IKVM.Reflection/LocalVariableInfo.cs
new file mode 100644 (file)
index 0000000..a6875d9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+       public class LocalVariableInfo
+       {
+               private readonly int index;
+               private readonly Type type;
+               private readonly bool pinned;
+
+               internal LocalVariableInfo(int index, Type type, bool pinned)
+               {
+                       this.index = index;
+                       this.type = type;
+                       this.pinned = pinned;
+               }
+
+               public virtual bool IsPinned
+               {
+                       get { return pinned; }
+               }
+
+               public virtual int LocalIndex
+               {
+                       get { return index; }
+               }
+
+               public virtual Type LocalType
+               {
+                       get { return type; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/ManifestResourceInfo.cs b/mcs/class/IKVM.Reflection/ManifestResourceInfo.cs
new file mode 100644 (file)
index 0000000..a17b0d1
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+       public class ManifestResourceInfo
+       {
+               private readonly ModuleReader module;
+               private readonly int index;
+
+               internal ManifestResourceInfo(ModuleReader module, int index)
+               {
+                       this.module = module;
+                       this.index = index;
+               }
+
+               public ResourceLocation ResourceLocation
+               {
+                       get
+                       {
+                               int implementation = module.ManifestResource.records[index].Implementation;
+                               if ((implementation >> 24) == AssemblyRefTable.Index)
+                               {
+                                       //return ResourceLocation.ContainedInAnotherAssembly;
+                                       throw new NotImplementedException();
+                               }
+                               else if ((implementation >> 24) == FileTable.Index)
+                               {
+                                       if ((implementation & 0xFFFFFF) == 0)
+                                       {
+                                               return ResourceLocation.ContainedInManifestFile | ResourceLocation.Embedded;
+                                       }
+                                       return 0;
+                               }
+                               else
+                               {
+                                       throw new BadImageFormatException();
+                               }
+                       }
+               }
+
+               public Assembly ReferencedAssembly
+               {
+                       get { throw new NotImplementedException(); }
+               }
+
+               public string FileName
+               {
+                       get
+                       {
+                               int implementation = module.ManifestResource.records[index].Implementation;
+                               if ((implementation >> 24) == FileTable.Index)
+                               {
+                                       if ((implementation & 0xFFFFFF) == 0)
+                                       {
+                                               return null;
+                                       }
+                                       else
+                                       {
+                                               return module.GetString(module.File.records[(implementation & 0xFFFFFF) - 1].Name);
+                                       }
+                               }
+                               throw new NotImplementedException();
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MarshalSpec.cs b/mcs/class/IKVM.Reflection/MarshalSpec.cs
new file mode 100644 (file)
index 0000000..7078196
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+  Copyright (C) 2008, 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+       static class MarshalSpec
+       {
+               private const UnmanagedType NATIVE_TYPE_MAX = (UnmanagedType)0x50;
+
+               internal static CustomAttributeData GetMarshalAsAttribute(Module module, int token)
+               {
+                       // TODO use binary search?
+                       for (int i = 0; i < module.FieldMarshal.records.Length; i++)
+                       {
+                               if (module.FieldMarshal.records[i].Parent == token)
+                               {
+                                       ByteReader blob = module.GetBlob(module.FieldMarshal.records[i].NativeType);
+                                       UnmanagedType unmanagedType = (UnmanagedType)blob.ReadCompressedInt();
+                                       UnmanagedType? arraySubType = null;
+                                       short? sizeParamIndex = null;
+                                       int? sizeConst = null;
+                                       VarEnum? safeArraySubType = null;
+                                       Type safeArrayUserDefinedSubType = null;
+                                       int? iidParameterIndex = null;
+                                       string marshalType = null;
+                                       string marshalCookie = null;
+                                       Type marshalTypeRef = null;
+                                       if (unmanagedType == UnmanagedType.LPArray)
+                                       {
+                                               arraySubType = (UnmanagedType)blob.ReadCompressedInt();
+                                               if (arraySubType == NATIVE_TYPE_MAX)
+                                               {
+                                                       arraySubType = null;
+                                               }
+                                               if (blob.Length != 0)
+                                               {
+                                                       sizeParamIndex = (short)blob.ReadCompressedInt();
+                                                       if (blob.Length != 0)
+                                                       {
+                                                               sizeConst = blob.ReadCompressedInt();
+                                                               if (blob.Length != 0 && blob.ReadCompressedInt() == 0)
+                                                               {
+                                                                       sizeParamIndex = null;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       else if (unmanagedType == UnmanagedType.SafeArray)
+                                       {
+                                               if (blob.Length != 0)
+                                               {
+                                                       safeArraySubType = (VarEnum)blob.ReadCompressedInt();
+                                                       if (blob.Length != 0)
+                                                       {
+                                                               safeArrayUserDefinedSubType = ReadType(module, blob);
+                                                       }
+                                               }
+                                       }
+                                       else if (unmanagedType == UnmanagedType.ByValArray)
+                                       {
+                                               sizeConst = blob.ReadCompressedInt();
+                                               if (blob.Length != 0)
+                                               {
+                                                       arraySubType = (UnmanagedType)blob.ReadCompressedInt();
+                                               }
+                                       }
+                                       else if (unmanagedType == UnmanagedType.ByValTStr)
+                                       {
+                                               sizeConst = blob.ReadCompressedInt();
+                                       }
+                                       else if (unmanagedType == UnmanagedType.Interface
+                                               || unmanagedType == UnmanagedType.IDispatch
+                                               || unmanagedType == UnmanagedType.IUnknown)
+                                       {
+                                               if (blob.Length != 0)
+                                               {
+                                                       iidParameterIndex = blob.ReadCompressedInt();
+                                               }
+                                       }
+                                       else if (unmanagedType == UnmanagedType.CustomMarshaler)
+                                       {
+                                               blob.ReadCompressedInt();
+                                               blob.ReadCompressedInt();
+                                               marshalType = ReadString(blob);
+                                               marshalCookie = ReadString(blob);
+                                               marshalTypeRef = module.Assembly.GetType(marshalType) ?? module.universe.GetType(marshalType);
+                                       }
+
+                                       Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute;
+                                       Type typeofUnmanagedType = module.universe.System_Runtime_InteropServices_UnmanagedType;
+                                       Type typeofVarEnum = module.universe.System_Runtime_InteropServices_VarEnum;
+                                       Type typeofType = module.universe.System_Type;
+                                       List<CustomAttributeNamedArgument> named = new List<CustomAttributeNamedArgument>();
+                                       if (arraySubType != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("ArraySubType"), new CustomAttributeTypedArgument(typeofUnmanagedType, arraySubType.Value)));
+                                       }
+                                       if (sizeParamIndex != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SizeParamIndex"), new CustomAttributeTypedArgument(module.universe.System_Int16, sizeParamIndex.Value)));
+                                       }
+                                       if (sizeConst != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SizeConst"), new CustomAttributeTypedArgument(module.universe.System_Int32, sizeConst.Value)));
+                                       }
+                                       if (safeArraySubType != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SafeArraySubType"), new CustomAttributeTypedArgument(typeofVarEnum, safeArraySubType.Value)));
+                                       }
+                                       if (safeArrayUserDefinedSubType != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SafeArrayUserDefinedSubType"), new CustomAttributeTypedArgument(typeofType, safeArrayUserDefinedSubType)));
+                                       }
+                                       if (iidParameterIndex != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("IidParameterIndex"), new CustomAttributeTypedArgument(module.universe.System_Int32, iidParameterIndex.Value)));
+                                       }
+                                       if (marshalType != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalType"), new CustomAttributeTypedArgument(module.universe.System_String, marshalType)));
+                                       }
+                                       if (marshalTypeRef != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalTypeRef"), new CustomAttributeTypedArgument(module.universe.System_Type, marshalTypeRef)));
+                                       }
+                                       if (marshalCookie != null)
+                                       {
+                                               named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalCookie"), new CustomAttributeTypedArgument(module.universe.System_String, marshalCookie)));
+                                       }
+                                       ConstructorInfo constructor = typeofMarshalAs.GetConstructor(new Type[] { typeofUnmanagedType });
+                                       return new CustomAttributeData(constructor, new object[] { unmanagedType }, named);
+                               }
+                       }
+                       throw new BadImageFormatException();
+               }
+
+               internal static void SetMarshalAsAttribute(ModuleBuilder module, int token, CustomAttributeBuilder attribute)
+               {
+                       attribute = attribute.DecodeBlob(module.Assembly);
+                       FieldMarshalTable.Record rec = new FieldMarshalTable.Record();
+                       rec.Parent = token;
+                       rec.NativeType = WriteMarshallingDescriptor(module, attribute);
+                       module.FieldMarshal.AddRecord(rec);
+               }
+
+               private static int WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute)
+               {
+                       UnmanagedType unmanagedType;
+                       object val = attribute.GetConstructorArgument(0);
+                       if (val is short)
+                       {
+                               unmanagedType = (UnmanagedType)(short)val;
+                       }
+                       else if (val is int)
+                       {
+                               unmanagedType = (UnmanagedType)(int)val;
+                       }
+                       else
+                       {
+                               unmanagedType = (UnmanagedType)val;
+                       }
+
+                       ByteBuffer bb = new ByteBuffer(5);
+                       bb.WriteCompressedInt((int)unmanagedType);
+
+                       if (unmanagedType == UnmanagedType.LPArray)
+                       {
+                               UnmanagedType arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType") ?? NATIVE_TYPE_MAX;
+                               bb.WriteCompressedInt((int)arraySubType);
+                               int? sizeParamIndex = attribute.GetFieldValue<short>("SizeParamIndex");
+                               int? sizeConst = attribute.GetFieldValue<int>("SizeConst");
+                               if (sizeParamIndex != null)
+                               {
+                                       bb.WriteCompressedInt(sizeParamIndex.Value);
+                                       if (sizeConst != null)
+                                       {
+                                               bb.WriteCompressedInt(sizeConst.Value);
+                                               bb.WriteCompressedInt(1); // flag that says that SizeParamIndex was specified
+                                       }
+                               }
+                               else if (sizeConst != null)
+                               {
+                                       bb.WriteCompressedInt(0); // SizeParamIndex
+                                       bb.WriteCompressedInt(sizeConst.Value);
+                                       bb.WriteCompressedInt(0); // flag that says that SizeParamIndex was not specified
+                               }
+                       }
+                       else if (unmanagedType == UnmanagedType.SafeArray)
+                       {
+                               VarEnum? safeArraySubType = attribute.GetFieldValue<VarEnum>("SafeArraySubType");
+                               if (safeArraySubType != null)
+                               {
+                                       bb.WriteCompressedInt((int)safeArraySubType);
+                                       Type safeArrayUserDefinedSubType = (Type)attribute.GetFieldValue("SafeArrayUserDefinedSubType");
+                                       if (safeArrayUserDefinedSubType != null)
+                                       {
+                                               WriteType(module, bb, safeArrayUserDefinedSubType);
+                                       }
+                               }
+                       }
+                       else if (unmanagedType == UnmanagedType.ByValArray)
+                       {
+                               bb.WriteCompressedInt(attribute.GetFieldValue<int>("SizeConst") ?? 1);
+                               UnmanagedType? arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType");
+                               if (arraySubType != null)
+                               {
+                                       bb.WriteCompressedInt((int)arraySubType);
+                               }
+                       }
+                       else if (unmanagedType == UnmanagedType.ByValTStr)
+                       {
+                               bb.WriteCompressedInt(attribute.GetFieldValue<int>("SizeConst").Value);
+                       }
+                       else if (unmanagedType == UnmanagedType.Interface
+                               || unmanagedType == UnmanagedType.IDispatch
+                               || unmanagedType == UnmanagedType.IUnknown)
+                       {
+                               int? iidParameterIndex = attribute.GetFieldValue<int>("IidParameterIndex");
+                               if (iidParameterIndex != null)
+                               {
+                                       bb.WriteCompressedInt(iidParameterIndex.Value);
+                               }
+                       }
+                       else if (unmanagedType == UnmanagedType.CustomMarshaler)
+                       {
+                               bb.WriteCompressedInt(0);
+                               bb.WriteCompressedInt(0);
+                               string marshalType = (string)attribute.GetFieldValue("MarshalType");
+                               if (marshalType != null)
+                               {
+                                       WriteString(bb, marshalType);
+                               }
+                               else
+                               {
+                                       WriteType(module, bb, (Type)attribute.GetFieldValue("MarshalTypeRef"));
+                               }
+                               WriteString(bb, (string)attribute.GetFieldValue("MarshalCookie") ?? "");
+                       }
+
+                       return module.Blobs.Add(bb);
+               }
+
+               private static Type ReadType(Module module, ByteReader br)
+               {
+                       string str = ReadString(br);
+                       if (str == "")
+                       {
+                               return null;
+                       }
+                       return module.Assembly.GetType(str) ?? module.universe.GetType(str, true);
+               }
+
+               private static void WriteType(Module module, ByteBuffer bb, Type type)
+               {
+                       WriteString(bb, type.Assembly == module.Assembly ? type.FullName : type.AssemblyQualifiedName);
+               }
+
+               private static string ReadString(ByteReader br)
+               {
+                       return Encoding.UTF8.GetString(br.ReadBytes(br.ReadCompressedInt()));
+               }
+
+               private static void WriteString(ByteBuffer bb, string str)
+               {
+                       byte[] buf = Encoding.UTF8.GetBytes(str);
+                       bb.WriteCompressedInt(buf.Length);
+                       bb.Write(buf);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MemberInfo.cs b/mcs/class/IKVM.Reflection/MemberInfo.cs
new file mode 100644 (file)
index 0000000..5406c32
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+// disable warnings that complain about us having == and != operators without also overriding Equals/GetHashCode,
+// this is intentional because most subtypes use reference equality
+#pragma warning disable 660, 661
+       public abstract class MemberInfo : ICustomAttributeProvider
+       {
+               public abstract string Name { get; }
+               public abstract Type DeclaringType { get; }
+               public abstract MemberTypes MemberType { get; }
+
+               public virtual int MetadataToken
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public abstract Module Module
+               {
+                       get;
+               }
+
+               public bool IsDefined(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+               }
+
+               public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+               }
+
+               public static bool operator ==(MemberInfo m1, MemberInfo m2)
+               {
+                       return ReferenceEquals(m1, m2) || (!ReferenceEquals(m1, null) && m1.Equals(m2));
+               }
+
+               public static bool operator !=(MemberInfo m1, MemberInfo m2)
+               {
+                       return !(m1 == m2);
+               }
+
+               internal virtual IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return this.Module.GetCustomAttributes(this.MetadataToken, attributeType);
+               }
+
+               internal static bool BindingFlagsMatch(bool state, BindingFlags flags, BindingFlags trueFlag, BindingFlags falseFlag)
+               {
+                       return (state && (flags & trueFlag) == trueFlag)
+                               || (!state && (flags & falseFlag) == falseFlag);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Metadata/CliHeader.cs b/mcs/class/IKVM.Reflection/Metadata/CliHeader.cs
new file mode 100644 (file)
index 0000000..90258c3
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System.IO;
+
+namespace IKVM.Reflection.Metadata
+{
+       sealed class CliHeader
+       {
+               internal const uint COMIMAGE_FLAGS_ILONLY = 0x00000001;
+               internal const uint COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
+               internal const uint COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008;
+               internal const uint COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = 0x00000010;
+
+               internal uint Cb = 0x48;
+               internal ushort MajorRuntimeVersion;
+               internal ushort MinorRuntimeVersion;
+               internal uint MetaDataRVA;
+               internal uint MetaDataSize;
+               internal uint Flags;
+               internal uint EntryPointToken;
+               internal uint ResourcesRVA;
+               internal uint ResourcesSize;
+               internal uint StrongNameSignatureRVA;
+               internal uint StrongNameSignatureSize;
+               internal ulong CodeManagerTable;
+               internal uint VTableFixupsRVA;
+               internal uint VTableFixupsSize;
+               internal ulong ExportAddressTableJumps;
+               internal ulong ManagedNativeHeader;
+
+               internal void Read(BinaryReader br)
+               {
+                       Cb = br.ReadUInt32();
+                       MajorRuntimeVersion = br.ReadUInt16();
+                       MinorRuntimeVersion = br.ReadUInt16();
+                       MetaDataRVA = br.ReadUInt32();
+                       MetaDataSize = br.ReadUInt32();
+                       Flags = br.ReadUInt32();
+                       EntryPointToken = br.ReadUInt32();
+                       ResourcesRVA = br.ReadUInt32();
+                       ResourcesSize = br.ReadUInt32();
+                       StrongNameSignatureRVA = br.ReadUInt32();
+                       StrongNameSignatureSize = br.ReadUInt32();
+                       CodeManagerTable = br.ReadUInt32();
+                       VTableFixupsRVA = br.ReadUInt32();
+                       VTableFixupsSize = br.ReadUInt32();
+                       ExportAddressTableJumps = br.ReadUInt32();
+                       ManagedNativeHeader = br.ReadUInt32();
+               }
+
+               internal void Write(IKVM.Reflection.Writer.MetadataWriter mw)
+               {
+                       mw.Write(Cb);
+                       mw.Write(MajorRuntimeVersion);
+                       mw.Write(MinorRuntimeVersion);
+                       mw.Write(MetaDataRVA);
+                       mw.Write(MetaDataSize);
+                       mw.Write(Flags);
+                       mw.Write(EntryPointToken);
+                       mw.Write(ResourcesRVA);
+                       mw.Write(ResourcesSize);
+                       mw.Write(StrongNameSignatureRVA);
+                       mw.Write(StrongNameSignatureSize);
+                       mw.Write(CodeManagerTable);
+                       mw.Write(VTableFixupsRVA);
+                       mw.Write(VTableFixupsSize);
+                       mw.Write(ExportAddressTableJumps);
+                       mw.Write(ManagedNativeHeader);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Metadata/MetadataRW.cs b/mcs/class/IKVM.Reflection/Metadata/MetadataRW.cs
new file mode 100644 (file)
index 0000000..d03c8d6
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection.Metadata
+{
+       // base class for MetadataReader and MetadataWriter
+       abstract class MetadataRW
+       {
+               internal readonly bool bigStrings;
+               internal readonly bool bigGuids;
+               internal readonly bool bigBlobs;
+               internal readonly bool bigResolutionScope;
+               internal readonly bool bigTypeDefOrRef;
+               internal readonly bool bigMemberRefParent;
+               internal readonly bool bigHasCustomAttribute;
+               internal readonly bool bigCustomAttributeType;
+               internal readonly bool bigMethodDefOrRef;
+               internal readonly bool bigHasConstant;
+               internal readonly bool bigHasSemantics;
+               internal readonly bool bigHasFieldMarshal;
+               internal readonly bool bigHasDeclSecurity;
+               internal readonly bool bigTypeOrMethodDef;
+               internal readonly bool bigMemberForwarded;
+               internal readonly bool bigImplementation;
+               internal readonly bool bigField;
+               internal readonly bool bigMethodDef;
+               internal readonly bool bigParam;
+               internal readonly bool bigTypeDef;
+               internal readonly bool bigProperty;
+               internal readonly bool bigEvent;
+               internal readonly bool bigGenericParam;
+               internal readonly bool bigModuleRef;
+
+               protected MetadataRW(Module module, bool bigStrings, bool bigGuids, bool bigBlobs)
+               {
+                       this.bigStrings = bigStrings;
+                       this.bigGuids = bigGuids;
+                       this.bigBlobs = bigBlobs;
+                       this.bigField = module.Field.IsBig;
+                       this.bigMethodDef = module.MethodDef.IsBig;
+                       this.bigParam = module.Param.IsBig;
+                       this.bigTypeDef = module.TypeDef.IsBig;
+                       this.bigProperty = module.Property.IsBig;
+                       this.bigEvent = module.Event.IsBig;
+                       this.bigGenericParam = module.GenericParam.IsBig;
+                       this.bigModuleRef = module.ModuleRef.IsBig;
+                       this.bigResolutionScope = IsBig(2, module.ModuleTable, module.ModuleRef, module.AssemblyRef, module.TypeRef);
+                       this.bigTypeDefOrRef = IsBig(2, module.TypeDef, module.TypeRef, module.TypeSpec);
+                       this.bigMemberRefParent = IsBig(3, module.TypeDef, module.TypeRef, module.ModuleRef, module.MethodDef, module.TypeSpec);
+                       this.bigMethodDefOrRef = IsBig(1, module.MethodDef, module.MemberRef);
+                       this.bigHasCustomAttribute = IsBig(5, module.MethodDef, module.Field, module.TypeRef, module.TypeDef, module.Param, module.InterfaceImpl, module.MemberRef,
+                               module.ModuleTable, /*module.Permission,*/ module.Property, module.Event, module.StandAloneSig, module.ModuleRef, module.TypeSpec, module.AssemblyTable,
+                               module.AssemblyRef, module.File, module.ExportedType, module.ManifestResource);
+                       this.bigCustomAttributeType = IsBig(3, module.MethodDef, module.MemberRef);
+                       this.bigHasConstant = IsBig(2, module.Field, module.Param, module.Property);
+                       this.bigHasSemantics = IsBig(1, module.Event, module.Property);
+                       this.bigHasFieldMarshal = IsBig(1, module.Field, module.Param);
+                       this.bigHasDeclSecurity = IsBig(2, module.TypeDef, module.MethodDef, module.AssemblyTable);
+                       this.bigTypeOrMethodDef = IsBig(1, module.TypeDef, module.MethodDef);
+                       this.bigMemberForwarded = IsBig(1, module.Field, module.MethodDef);
+                       this.bigImplementation = IsBig(2, module.File, module.AssemblyRef, module.ExportedType);
+               }
+
+               private static bool IsBig(int bitsUsed, params Table[] tables)
+               {
+                       int limit = 1 << (16 - bitsUsed);
+                       foreach (Table table in tables)
+                       {
+                               if (table.RowCount >= limit)
+                               {
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Metadata/Tables.cs b/mcs/class/IKVM.Reflection/Metadata/Tables.cs
new file mode 100644 (file)
index 0000000..d734330
--- /dev/null
@@ -0,0 +1,2483 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection.Metadata
+{
+       internal abstract class Table
+       {
+               internal bool IsBig
+               {
+                       get { return RowCount > 65535; }
+               }
+
+               internal abstract int RowCount { get; set; }
+
+               internal abstract void Write(MetadataWriter mw);
+               internal abstract void Read(MetadataReader mr);
+
+               internal int GetLength(MetadataWriter md)
+               {
+                       return RowCount * GetRowSize(new RowSizeCalc(md));
+               }
+
+               protected abstract int GetRowSize(RowSizeCalc rsc);
+
+               protected sealed class RowSizeCalc
+               {
+                       private readonly MetadataWriter mw;
+                       private int size;
+
+                       internal RowSizeCalc(MetadataWriter mw)
+                       {
+                               this.mw = mw;
+                       }
+
+                       internal RowSizeCalc AddFixed(int size)
+                       {
+                               this.size += size;
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteStringIndex()
+                       {
+                               if (mw.bigStrings)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteGuidIndex()
+                       {
+                               if (mw.bigGuids)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteBlobIndex()
+                       {
+                               if (mw.bigBlobs)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteTypeDefOrRef()
+                       {
+                               if (mw.bigTypeDefOrRef)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteField()
+                       {
+                               if (mw.bigField)
+                               {
+                                       size += 4;
+                               }
+                               else
+                               {
+                                       size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteMethodDef()
+                       {
+                               if (mw.bigMethodDef)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteParam()
+                       {
+                               if (mw.bigParam)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteResolutionScope()
+                       {
+                               if (mw.bigResolutionScope)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteMemberRefParent()
+                       {
+                               if (mw.bigMemberRefParent)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteHasCustomAttribute()
+                       {
+                               if (mw.bigHasCustomAttribute)
+                               {
+                                       size += 4;
+                               }
+                               else
+                               {
+                                       size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteCustomAttributeType()
+                       {
+                               if (mw.bigCustomAttributeType)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteHasConstant()
+                       {
+                               if (mw.bigHasConstant)
+                               {
+                                       size += 4;
+                               }
+                               else
+                               {
+                                       size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteTypeDef()
+                       {
+                               if (mw.bigTypeDef)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteMethodDefOrRef()
+                       {
+                               if (mw.bigMethodDefOrRef)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteEvent()
+                       {
+                               if (mw.bigEvent)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteProperty()
+                       {
+                               if (mw.bigProperty)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteHasSemantics()
+                       {
+                               if (mw.bigHasSemantics)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteImplementation()
+                       {
+                               if (mw.bigImplementation)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteTypeOrMethodDef()
+                       {
+                               if (mw.bigTypeOrMethodDef)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteGenericParam()
+                       {
+                               if (mw.bigGenericParam)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteHasDeclSecurity()
+                       {
+                               if (mw.bigHasDeclSecurity)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteMemberForwarded()
+                       {
+                               if (mw.bigMemberForwarded)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteModuleRef()
+                       {
+                               if (mw.bigModuleRef)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal RowSizeCalc WriteHasFieldMarshal()
+                       {
+                               if (mw.bigHasFieldMarshal)
+                               {
+                                       this.size += 4;
+                               }
+                               else
+                               {
+                                       this.size += 2;
+                               }
+                               return this;
+                       }
+
+                       internal int Value
+                       {
+                               get { return size; }
+                       }
+               }
+       }
+
+       abstract class Table<T> : Table
+       {
+               internal T[] records = new T[1];
+               protected int rowCount;
+
+               internal sealed override int RowCount
+               {
+                       get { return rowCount; }
+                       set { rowCount = value; records = new T[value]; }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal int AddRecord(T newRecord)
+               {
+                       if (rowCount == records.Length)
+                       {
+                               T[] newarr = new T[records.Length * 2];
+                               Array.Copy(records, newarr, records.Length);
+                               records = newarr;
+                       }
+                       records[rowCount++] = newRecord;
+                       return rowCount;
+               }
+
+               internal int AddVirtualRecord()
+               {
+                       return ++rowCount;
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       throw new InvalidOperationException();
+               }
+       }
+
+       sealed class ModuleTable : Table<ModuleTable.Record>
+       {
+               internal const int Index = 0x00;
+
+               internal struct Record
+               {
+                       internal short Generation;
+                       internal int Name; // -> StringHeap
+                       internal int Mvid; // -> GuidHeap
+                       internal int EncId; // -> GuidHeap
+                       internal int EncBaseId; // -> GuidHeap
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Generation = mr.ReadInt16();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Mvid = mr.ReadGuidIndex();
+                               records[i].EncId = mr.ReadGuidIndex();
+                               records[i].EncBaseId = mr.ReadGuidIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Generation);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteGuidIndex(records[i].Mvid);
+                               mw.WriteGuidIndex(records[i].EncId);
+                               mw.WriteGuidIndex(records[i].EncBaseId);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteStringIndex()
+                               .WriteGuidIndex()
+                               .WriteGuidIndex()
+                               .WriteGuidIndex()
+                               .Value;
+               }
+
+               internal void Add(short generation, int name, int mvid, int encid, int encbaseid)
+               {
+                       Record record = new Record();
+                       record.Generation = generation;
+                       record.Name = name;
+                       record.Mvid = mvid;
+                       record.EncId = encid;
+                       record.EncBaseId = encbaseid;
+                       AddRecord(record);
+               }
+       }
+
+       sealed class TypeRefTable : Table<TypeRefTable.Record>
+       {
+               internal const int Index = 0x01;
+
+               internal struct Record
+               {
+                       internal int ResolutionScope;
+                       internal int TypeName;
+                       internal int TypeNameSpace;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].ResolutionScope = mr.ReadResolutionScope();
+                               records[i].TypeName = mr.ReadStringIndex();
+                               records[i].TypeNameSpace = mr.ReadStringIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteResolutionScope(records[i].ResolutionScope);
+                               mw.WriteStringIndex(records[i].TypeName);
+                               mw.WriteStringIndex(records[i].TypeNameSpace);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteResolutionScope()
+                               .WriteStringIndex()
+                               .WriteStringIndex()
+                               .Value;
+               }
+       }
+
+       sealed class TypeDefTable : Table<TypeDefTable.Record>
+       {
+               internal const int Index = 0x02;
+
+               internal struct Record
+               {
+                       internal int Flags;
+                       internal int TypeName;
+                       internal int TypeNamespace;
+                       internal int Extends;
+                       internal int FieldList;
+                       internal int MethodList;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Flags = mr.ReadInt32();
+                               records[i].TypeName = mr.ReadStringIndex();
+                               records[i].TypeNamespace = mr.ReadStringIndex();
+                               records[i].Extends = mr.ReadTypeDefOrRef();
+                               records[i].FieldList = mr.ReadField();
+                               records[i].MethodList = mr.ReadMethodDef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       mw.ModuleBuilder.WriteTypeDefTable(mw);
+               }
+
+               internal int AllocToken()
+               {
+                       return 0x02000000 + AddVirtualRecord();
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(4)
+                               .WriteStringIndex()
+                               .WriteStringIndex()
+                               .WriteTypeDefOrRef()
+                               .WriteField()
+                               .WriteMethodDef()
+                               .Value;
+               }
+       }
+
+       sealed class FieldTable : Table<FieldTable.Record>
+       {
+               internal const int Index = 0x04;
+
+               internal struct Record
+               {
+                       internal short Flags;
+                       internal int Name;
+                       internal int Signature;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Flags = mr.ReadInt16();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Signature = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       mw.ModuleBuilder.WriteFieldTable(mw);
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteStringIndex()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+       }
+
+       sealed class MethodDefTable : Table<MethodDefTable.Record>
+       {
+               internal const int Index = 0x06;
+               private int baseRVA;
+
+               internal struct Record
+               {
+                       internal int RVA;
+                       internal short ImplFlags;
+                       internal short Flags;
+                       internal int Name;
+                       internal int Signature;
+                       internal int ParamList;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].RVA = mr.ReadInt32();
+                               records[i].ImplFlags = mr.ReadInt16();
+                               records[i].Flags = mr.ReadInt16();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Signature = mr.ReadBlobIndex();
+                               records[i].ParamList = mr.ReadParam();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       mw.ModuleBuilder.WriteMethodDefTable(baseRVA, mw);
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(8)
+                               .WriteStringIndex()
+                               .WriteBlobIndex()
+                               .WriteParam()
+                               .Value;
+               }
+
+               internal void Fixup(TextSection code)
+               {
+                       baseRVA = (int)code.MethodBodiesRVA;
+               }
+       }
+
+       sealed class ParamTable : Table<ParamTable.Record>
+       {
+               internal const int Index = 0x08;
+
+               internal struct Record
+               {
+                       internal short Flags;
+                       internal short Sequence;
+                       internal int Name;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Flags = mr.ReadInt16();
+                               records[i].Sequence = mr.ReadInt16();
+                               records[i].Name = mr.ReadStringIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       mw.ModuleBuilder.WriteParamTable(mw);
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(4)
+                               .WriteStringIndex()
+                               .Value;
+               }
+       }
+
+       sealed class InterfaceImplTable : Table<InterfaceImplTable.Record>, IComparer<InterfaceImplTable.Record>
+       {
+               internal const int Index = 0x09;
+
+               internal struct Record
+               {
+                       internal int Class;
+                       internal int Interface;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Class = mr.ReadTypeDef();
+                               records[i].Interface = mr.ReadTypeDefOrRef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteTypeDef(records[i].Class);
+                               mw.WriteEncodedTypeDefOrRef(records[i].Interface);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteTypeDef()
+                               .WriteTypeDefOrRef()
+                               .Value;
+               }
+
+               internal void Fixup()
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               int token = records[i].Interface;
+                               switch (token >> 24)
+                               {
+                                       case 0:
+                                               break;
+                                       case TypeDefTable.Index:
+                                               token = (token & 0xFFFFFF) << 2 | 0;
+                                               break;
+                                       case TypeRefTable.Index:
+                                               token = (token & 0xFFFFFF) << 2 | 1;
+                                               break;
+                                       case TypeSpecTable.Index:
+                                               token = (token & 0xFFFFFF) << 2 | 2;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                               records[i].Interface = token;
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       if (x.Class == y.Class)
+                       {
+                               return x.Interface == y.Interface ? 0 : (x.Interface > y.Interface ? 1 : -1);
+                       }
+                       return x.Class > y.Class ? 1 : -1;
+               }
+       }
+
+       sealed class MemberRefTable : Table<MemberRefTable.Record>
+       {
+               internal const int Index = 0x0A;
+
+               internal struct Record
+               {
+                       internal int Class;
+                       internal int Name;
+                       internal int Signature;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Class = mr.ReadMemberRefParent();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Signature = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteMemberRefParent(records[i].Class);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteBlobIndex(records[i].Signature);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteMemberRefParent()
+                               .WriteStringIndex()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+
+               internal int FindOrAddRecord(Record record)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i].Class == record.Class
+                                       && records[i].Name == record.Name
+                                       && records[i].Signature == record.Signature)
+                               {
+                                       return i + 1;
+                               }
+                       }
+                       return AddRecord(record);
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (moduleBuilder.IsPseudoToken(records[i].Class))
+                               {
+                                       records[i].Class = moduleBuilder.ResolvePseudoToken(records[i].Class);
+                               }
+                       }
+               }
+       }
+
+       sealed class ConstantTable : Table<ConstantTable.Record>, IComparer<ConstantTable.Record>
+       {
+               internal const int Index = 0x0B;
+
+               internal struct Record
+               {
+                       internal short Type;
+                       internal int Parent;
+                       internal int Value;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Type = mr.ReadInt16();
+                               records[i].Parent = mr.ReadHasConstant();
+                               records[i].Value = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Type);
+                               mw.WriteHasConstant(records[i].Parent);
+                               mw.WriteBlobIndex(records[i].Value);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteHasConstant()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               int token = records[i].Parent;
+                               if (moduleBuilder.IsPseudoToken(token))
+                               {
+                                       token = moduleBuilder.ResolvePseudoToken(token);
+                               }
+                               // do the HasConstant encoding, so that we can sort the table
+                               switch (token >> 24)
+                               {
+                                       case FieldTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 2 | 0;
+                                               break;
+                                       case ParamTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 2 | 1;
+                                               break;
+                                       case PropertyTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 2 | 2;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+               }
+
+               internal object GetRawConstantValue(Module module, int parent)
+               {
+                       // TODO use binary search (if sorted)
+                       for (int i = 0; i < module.Constant.records.Length; i++)
+                       {
+                               if (module.Constant.records[i].Parent == parent)
+                               {
+                                       ByteReader br = module.GetBlob(module.Constant.records[i].Value);
+                                       switch (module.Constant.records[i].Type)
+                                       {
+                                               // see ModuleBuilder.AddConstant for the encodings
+                                               case Signature.ELEMENT_TYPE_BOOLEAN:
+                                                       return br.ReadByte() != 0;
+                                               case Signature.ELEMENT_TYPE_I1:
+                                                       return br.ReadSByte();
+                                               case Signature.ELEMENT_TYPE_I2:
+                                                       return br.ReadInt16();
+                                               case Signature.ELEMENT_TYPE_I4:
+                                                       return br.ReadInt32();
+                                               case Signature.ELEMENT_TYPE_I8:
+                                                       return br.ReadInt64();
+                                               case Signature.ELEMENT_TYPE_U1:
+                                                       return br.ReadByte();
+                                               case Signature.ELEMENT_TYPE_U2:
+                                                       return br.ReadUInt16();
+                                               case Signature.ELEMENT_TYPE_U4:
+                                                       return br.ReadUInt32();
+                                               case Signature.ELEMENT_TYPE_U8:
+                                                       return br.ReadUInt64();
+                                               case Signature.ELEMENT_TYPE_R4:
+                                                       return br.ReadSingle();
+                                               case Signature.ELEMENT_TYPE_R8:
+                                                       return br.ReadDouble();
+                                               case Signature.ELEMENT_TYPE_CHAR:
+                                                       return br.ReadChar();
+                                               case Signature.ELEMENT_TYPE_STRING:
+                                                       {
+                                                               char[] chars = new char[br.Length / 2];
+                                                               for (int j = 0; j < chars.Length; j++)
+                                                               {
+                                                                       chars[j] = br.ReadChar();
+                                                               }
+                                                               return new String(chars);
+                                                       }
+                                               case Signature.ELEMENT_TYPE_CLASS:
+                                                       if (br.ReadInt32() != 0)
+                                                       {
+                                                               throw new BadImageFormatException();
+                                                       }
+                                                       return null;
+                                               default:
+                                                       throw new BadImageFormatException();
+                                       }
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+       }
+
+       sealed class CustomAttributeTable : Table<CustomAttributeTable.Record>, IComparer<CustomAttributeTable.Record>
+       {
+               internal const int Index = 0x0C;
+
+               internal struct Record
+               {
+                       internal int Parent;
+                       internal int Type;
+                       internal int Value;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Parent = mr.ReadHasCustomAttribute();
+                               records[i].Type = mr.ReadCustomAttributeType();
+                               records[i].Value = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteHasCustomAttribute(records[i].Parent);
+                               mw.WriteCustomAttributeType(records[i].Type);
+                               mw.WriteBlobIndex(records[i].Value);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteHasCustomAttribute()
+                               .WriteCustomAttributeType()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       int[] genericParamFixup = moduleBuilder.GenericParam.GetIndexFixup();
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (moduleBuilder.IsPseudoToken(records[i].Type))
+                               {
+                                       records[i].Type = moduleBuilder.ResolvePseudoToken(records[i].Type);
+                               }
+                               int token = records[i].Parent;
+                               if (moduleBuilder.IsPseudoToken(token))
+                               {
+                                       token = moduleBuilder.ResolvePseudoToken(token);
+                               }
+                               // do the HasCustomAttribute encoding, so that we can sort the table
+                               switch (token >> 24)
+                               {
+                                       case MethodDefTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 0;
+                                               break;
+                                       case FieldTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 1;
+                                               break;
+                                       case TypeRefTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 2;
+                                               break;
+                                       case TypeDefTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 3;
+                                               break;
+                                       case ParamTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 4;
+                                               break;
+                                       case InterfaceImplTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 5;
+                                               break;
+                                       case MemberRefTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 6;
+                                               break;
+                                       case ModuleTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 7;
+                                               break;
+                                       // Permission (8) table doesn't exist in the spec
+                                       case PropertyTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 9;
+                                               break;
+                                       case EventTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 10;
+                                               break;
+                                       case StandAloneSigTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 11;
+                                               break;
+                                       case ModuleRefTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 12;
+                                               break;
+                                       case TypeSpecTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 13;
+                                               break;
+                                       case AssemblyTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 14;
+                                               break;
+                                       case AssemblyRefTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 15;
+                                               break;
+                                       case FileTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 16;
+                                               break;
+                                       case ExportedTypeTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 17;
+                                               break;
+                                       case ManifestResourceTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 5 | 18;
+                                               break;
+                                       case GenericParamTable.Index:
+                                               records[i].Parent = (genericParamFixup[(token & 0xFFFFFF) - 1] + 1) << 5 | 19;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+               }
+       }
+
+       sealed class FieldMarshalTable : Table<FieldMarshalTable.Record>, IComparer<FieldMarshalTable.Record>
+       {
+               internal const int Index = 0x0D;
+
+               internal struct Record
+               {
+                       internal int Parent;
+                       internal int NativeType;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Parent = mr.ReadHasFieldMarshal();
+                               records[i].NativeType = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteHasFieldMarshal(records[i].Parent);
+                               mw.WriteBlobIndex(records[i].NativeType);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteHasFieldMarshal()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               int token = moduleBuilder.ResolvePseudoToken(records[i].Parent);
+                               // do the HasFieldMarshal encoding, so that we can sort the table
+                               switch (token >> 24)
+                               {
+                                       case FieldTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 1 | 0;
+                                               break;
+                                       case ParamTable.Index:
+                                               records[i].Parent = (token & 0xFFFFFF) << 1 | 1;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+               }
+       }
+
+       sealed class DeclSecurityTable : Table<DeclSecurityTable.Record>, IComparer<DeclSecurityTable.Record>
+       {
+               internal const int Index = 0x0E;
+
+               internal struct Record
+               {
+                       internal short Action;
+                       internal int Parent;
+                       internal int PermissionSet;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Action = mr.ReadInt16();
+                               records[i].Parent = mr.ReadHasDeclSecurity();
+                               records[i].PermissionSet = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Action);
+                               mw.WriteHasDeclSecurity(records[i].Parent);
+                               mw.WriteBlobIndex(records[i].PermissionSet);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteHasDeclSecurity()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               int token = records[i].Parent;
+                               if (moduleBuilder.IsPseudoToken(token))
+                               {
+                                       token = moduleBuilder.ResolvePseudoToken(token);
+                               }
+                               // do the HasDeclSecurity encoding, so that we can sort the table
+                               switch (token >> 24)
+                               {
+                                       case TypeDefTable.Index:
+                                               token = (token & 0xFFFFFF) << 2 | 0;
+                                               break;
+                                       case MethodDefTable.Index:
+                                               token = (token & 0xFFFFFF) << 2 | 1;
+                                               break;
+                                       case AssemblyTable.Index:
+                                               token = (token & 0xFFFFFF) << 2 | 2;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                               records[i].Parent = token;
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+               }
+       }
+
+       sealed class ClassLayoutTable : Table<ClassLayoutTable.Record>, IComparer<ClassLayoutTable.Record>
+       {
+               internal const int Index = 0x0f;
+
+               internal struct Record
+               {
+                       internal short PackingSize;
+                       internal int ClassSize;
+                       internal int Parent;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].PackingSize = mr.ReadInt16();
+                               records[i].ClassSize = mr.ReadInt32();
+                               records[i].Parent = mr.ReadTypeDef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       Array.Sort(records, 0, rowCount, this);
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].PackingSize);
+                               mw.Write(records[i].ClassSize);
+                               mw.WriteTypeDef(records[i].Parent);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(6)
+                               .WriteTypeDef()
+                               .Value;
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+               }
+
+               internal void GetLayout(int token, ref int pack, ref int size)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i].Parent == token)
+                               {
+                                       pack = records[i].PackingSize;
+                                       size = records[i].ClassSize;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       sealed class FieldLayoutTable : Table<FieldLayoutTable.Record>, IComparer<FieldLayoutTable.Record>
+       {
+               internal const int Index = 0x10;
+
+               internal struct Record
+               {
+                       internal int Offset;
+                       internal int Field;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Offset = mr.ReadInt32();
+                               records[i].Field = mr.ReadField();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Offset);
+                               mw.WriteField(records[i].Field);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(4)
+                               .WriteField()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
+               }
+       }
+
+       sealed class StandAloneSigTable : Table<int>
+       {
+               internal const int Index = 0x11;
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i] = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteBlobIndex(records[i]);
+                       }
+               }
+
+               protected override int GetRowSize(Table.RowSizeCalc rsc)
+               {
+                       return rsc.WriteBlobIndex().Value;
+               }
+
+               internal int FindOrAddRecord(int blob)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i] == blob)
+                               {
+                                       return i + 1;
+                               }
+                       }
+                       return AddRecord(blob);
+               }
+       }
+
+       sealed class EventMapTable : Table<EventMapTable.Record>
+       {
+               internal const int Index = 0x12;
+
+               internal struct Record
+               {
+                       internal int Parent;
+                       internal int EventList;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Parent = mr.ReadTypeDef();
+                               records[i].EventList = mr.ReadEvent();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteTypeDef(records[i].Parent);
+                               mw.WriteEvent(records[i].EventList);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteTypeDef()
+                               .WriteEvent()
+                               .Value;
+               }
+       }
+
+       sealed class EventTable : Table<EventTable.Record>
+       {
+               internal const int Index = 0x14;
+
+               internal struct Record
+               {
+                       internal short EventFlags;
+                       internal int Name;
+                       internal int EventType;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].EventFlags = mr.ReadInt16();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].EventType = mr.ReadTypeDefOrRef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].EventFlags);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteTypeDefOrRef(records[i].EventType);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteStringIndex()
+                               .WriteTypeDefOrRef()
+                               .Value;
+               }
+       }
+
+       sealed class PropertyMapTable : Table<PropertyMapTable.Record>
+       {
+               internal const int Index = 0x15;
+
+               internal struct Record
+               {
+                       internal int Parent;
+                       internal int PropertyList;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Parent = mr.ReadTypeDef();
+                               records[i].PropertyList = mr.ReadProperty();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteTypeDef(records[i].Parent);
+                               mw.WriteProperty(records[i].PropertyList);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteTypeDef()
+                               .WriteProperty()
+                               .Value;
+               }
+       }
+
+       sealed class PropertyTable : Table<PropertyTable.Record>
+       {
+               internal const int Index = 0x17;
+
+               internal struct Record
+               {
+                       internal short Flags;
+                       internal int Name;
+                       internal int Type;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Flags = mr.ReadInt16();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Type = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Flags);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteBlobIndex(records[i].Type);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteStringIndex()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+       }
+
+       sealed class MethodSemanticsTable : Table<MethodSemanticsTable.Record>, IComparer<MethodSemanticsTable.Record>
+       {
+               internal const int Index = 0x18;
+
+               // semantics
+               internal const short Setter = 0x0001;
+               internal const short Getter = 0x0002;
+               internal const short Other = 0x0004;
+               internal const short AddOn = 0x0008;
+               internal const short RemoveOn = 0x0010;
+               internal const short Fire = 0x0020;
+
+               internal struct Record
+               {
+                       internal short Semantics;
+                       internal int Method;
+                       internal int Association;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Semantics = mr.ReadInt16();
+                               records[i].Method = mr.ReadMethodDef();
+                               records[i].Association = mr.ReadHasSemantics();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Semantics);
+                               mw.WriteMethodDef(records[i].Method);
+                               mw.WriteHasSemantics(records[i].Association);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteMethodDef()
+                               .WriteHasSemantics()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (moduleBuilder.IsPseudoToken(records[i].Method))
+                               {
+                                       records[i].Method = moduleBuilder.ResolvePseudoToken(records[i].Method);
+                               }
+                               int token = records[i].Association;
+                               // do the HasSemantics encoding, so that we can sort the table
+                               switch (token >> 24)
+                               {
+                                       case EventTable.Index:
+                                               token = (token & 0xFFFFFF) << 1 | 0;
+                                               break;
+                                       case PropertyTable.Index:
+                                               token = (token & 0xFFFFFF) << 1 | 1;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                               records[i].Association = token;
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Association == y.Association ? 0 : (x.Association > y.Association ? 1 : -1);
+               }
+
+               internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
+               {
+                       int i = 0;
+                       return GetNextMethod(module, token, nonPublic, semantics, ref i);
+               }
+
+               internal MethodInfo[] GetMethods(Module module, int token, bool nonPublic, short semantics)
+               {
+                       List<MethodInfo> methods = new List<MethodInfo>();
+                       MethodInfo method;
+                       for (int i = 0; (method = GetNextMethod(module, token, nonPublic, semantics, ref i)) != null; )
+                       {
+                               methods.Add(method);
+                       }
+                       return methods.ToArray();
+               }
+
+               private MethodInfo GetNextMethod(Module module, int token, bool nonPublic, short semantics, ref int i)
+               {
+                       // TODO use binary search?
+                       for (; i < records.Length; i++)
+                       {
+                               if (records[i].Association == token)
+                               {
+                                       if ((records[i].Semantics & semantics) != 0)
+                                       {
+                                               MethodInfo method = (MethodInfo)module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
+                                               if (nonPublic || method.IsPublic)
+                                               {
+                                                       i++;
+                                                       return method;
+                                               }
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
+               internal void ComputeFlags(Module module, int token, out bool isPublic, out bool isStatic)
+               {
+                       isPublic = false;
+                       isStatic = false;
+                       MethodInfo method;
+                       for (int i = 0; (method = GetNextMethod(module, token, true, -1, ref i)) != null; )
+                       {
+                               if (method.IsPublic)
+                               {
+                                       isPublic = true;
+                               }
+                               if (method.IsStatic)
+                               {
+                                       isStatic = true;
+                               }
+                       }
+               }
+       }
+
+       sealed class MethodImplTable : Table<MethodImplTable.Record>, IComparer<MethodImplTable.Record>
+       {
+               internal const int Index = 0x19;
+
+               internal struct Record
+               {
+                       internal int Class;
+                       internal int MethodBody;
+                       internal int MethodDeclaration;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Class = mr.ReadTypeDef();
+                               records[i].MethodBody = mr.ReadMethodDefOrRef();
+                               records[i].MethodDeclaration = mr.ReadMethodDefOrRef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteTypeDef(records[i].Class);
+                               mw.WriteMethodDefOrRef(records[i].MethodBody);
+                               mw.WriteMethodDefOrRef(records[i].MethodDeclaration);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteTypeDef()
+                               .WriteMethodDefOrRef()
+                               .WriteMethodDefOrRef()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (moduleBuilder.IsPseudoToken(records[i].MethodBody))
+                               {
+                                       records[i].MethodBody = moduleBuilder.ResolvePseudoToken(records[i].MethodBody);
+                               }
+                               if (moduleBuilder.IsPseudoToken(records[i].MethodDeclaration))
+                               {
+                                       records[i].MethodDeclaration = moduleBuilder.ResolvePseudoToken(records[i].MethodDeclaration);
+                               }
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Class == y.Class ? 0 : (x.Class > y.Class ? 1 : -1);
+               }
+       }
+
+       sealed class ModuleRefTable : Table<int>
+       {
+               internal const int Index = 0x1A;
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i] = mr.ReadStringIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteStringIndex(records[i]);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteStringIndex()
+                               .Value;
+               }
+
+               internal int FindOrAddRecord(int str)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i] == str)
+                               {
+                                       return i + 1;
+                               }
+                       }
+                       return AddRecord(str);
+               }
+       }
+
+       sealed class TypeSpecTable : Table<int>
+       {
+               internal const int Index = 0x1B;
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i] = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteBlobIndex(records[i]);
+                       }
+               }
+
+               protected override int GetRowSize(Table.RowSizeCalc rsc)
+               {
+                       return rsc.WriteBlobIndex().Value;
+               }
+       }
+
+       sealed class ImplMapTable : Table<ImplMapTable.Record>, IComparer<ImplMapTable.Record>
+       {
+               internal const int Index = 0x1C;
+
+               internal struct Record
+               {
+                       internal short MappingFlags;
+                       internal int MemberForwarded;
+                       internal int ImportName;
+                       internal int ImportScope;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].MappingFlags = mr.ReadInt16();
+                               records[i].MemberForwarded = mr.ReadMemberForwarded();
+                               records[i].ImportName = mr.ReadStringIndex();
+                               records[i].ImportScope = mr.ReadModuleRef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].MappingFlags);
+                               mw.WriteMemberForwarded(records[i].MemberForwarded);
+                               mw.WriteStringIndex(records[i].ImportName);
+                               mw.WriteModuleRef(records[i].ImportScope);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(2)
+                               .WriteMemberForwarded()
+                               .WriteStringIndex()
+                               .WriteModuleRef()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (moduleBuilder.IsPseudoToken(records[i].MemberForwarded))
+                               {
+                                       records[i].MemberForwarded = moduleBuilder.ResolvePseudoToken(records[i].MemberForwarded);
+                               }
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.MemberForwarded == y.MemberForwarded ? 0 : (x.MemberForwarded > y.MemberForwarded ? 1 : -1);
+               }
+       }
+
+       sealed class FieldRVATable : Table<FieldRVATable.Record>, IComparer<FieldRVATable.Record>
+       {
+               internal const int Index = 0x1D;
+
+               internal struct Record
+               {
+                       internal int RVA;
+                       internal int Field;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].RVA = mr.ReadInt32();
+                               records[i].Field = mr.ReadField();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].RVA);
+                               mw.WriteField(records[i].Field);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(4)
+                               .WriteField()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder, int sdataRVA)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               records[i].RVA += sdataRVA;
+                               if (moduleBuilder.IsPseudoToken(records[i].Field))
+                               {
+                                       records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
+                               }
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
+               }
+       }
+
+       sealed class AssemblyTable : Table<AssemblyTable.Record>
+       {
+               internal const int Index = 0x20;
+
+               internal struct Record
+               {
+                       internal int HashAlgId;
+                       internal ushort MajorVersion;
+                       internal ushort MinorVersion;
+                       internal ushort BuildNumber;
+                       internal ushort RevisionNumber;
+                       internal int Flags;
+                       internal int PublicKey;
+                       internal int Name;
+                       internal int Culture;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].HashAlgId = mr.ReadInt32();
+                               records[i].MajorVersion = mr.ReadUInt16();
+                               records[i].MinorVersion = mr.ReadUInt16();
+                               records[i].BuildNumber = mr.ReadUInt16();
+                               records[i].RevisionNumber = mr.ReadUInt16();
+                               records[i].Flags = mr.ReadInt32();
+                               records[i].PublicKey = mr.ReadBlobIndex();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Culture = mr.ReadStringIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].HashAlgId);
+                               mw.Write(records[i].MajorVersion);
+                               mw.Write(records[i].MinorVersion);
+                               mw.Write(records[i].BuildNumber);
+                               mw.Write(records[i].RevisionNumber);
+                               mw.Write(records[i].Flags);
+                               mw.WriteBlobIndex(records[i].PublicKey);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteStringIndex(records[i].Culture);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(16)
+                               .WriteBlobIndex()
+                               .WriteStringIndex()
+                               .WriteStringIndex()
+                               .Value;
+               }
+       }
+
+       sealed class AssemblyRefTable : Table<AssemblyRefTable.Record>
+       {
+               internal const int Index = 0x23;
+
+               internal struct Record
+               {
+                       internal ushort MajorVersion;
+                       internal ushort MinorVersion;
+                       internal ushort BuildNumber;
+                       internal ushort RevisionNumber;
+                       internal int Flags;
+                       internal int PublicKeyOrToken;
+                       internal int Name;
+                       internal int Culture;
+                       internal int HashValue;
+               }
+
+               internal int FindOrAddRecord(Record rec)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i].Name == rec.Name
+                                       && records[i].MajorVersion == rec.MajorVersion
+                                       && records[i].MinorVersion == rec.MinorVersion
+                                       && records[i].BuildNumber == rec.BuildNumber
+                                       && records[i].RevisionNumber == rec.RevisionNumber
+                                       && records[i].Flags == rec.Flags
+                                       && records[i].PublicKeyOrToken == rec.PublicKeyOrToken
+                                       && records[i].Culture == rec.Culture
+                                       && records[i].HashValue == rec.HashValue
+                                       )
+                               {
+                                       return i + 1;
+                               }
+                       }
+                       return AddRecord(rec);
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].MajorVersion = mr.ReadUInt16();
+                               records[i].MinorVersion = mr.ReadUInt16();
+                               records[i].BuildNumber = mr.ReadUInt16();
+                               records[i].RevisionNumber = mr.ReadUInt16();
+                               records[i].Flags = mr.ReadInt32();
+                               records[i].PublicKeyOrToken = mr.ReadBlobIndex();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Culture = mr.ReadStringIndex();
+                               records[i].HashValue = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].MajorVersion);
+                               mw.Write(records[i].MinorVersion);
+                               mw.Write(records[i].BuildNumber);
+                               mw.Write(records[i].RevisionNumber);
+                               mw.Write(records[i].Flags);
+                               mw.WriteBlobIndex(records[i].PublicKeyOrToken);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteStringIndex(records[i].Culture);
+                               mw.WriteBlobIndex(records[i].HashValue);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(12)
+                               .WriteBlobIndex()
+                               .WriteStringIndex()
+                               .WriteStringIndex()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+       }
+
+       sealed class FileTable : Table<FileTable.Record>
+       {
+               internal const int Index = 0x26;
+
+               internal struct Record
+               {
+                       internal int Flags;
+                       internal int Name;
+                       internal int HashValue;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Flags = mr.ReadInt32();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].HashValue = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Flags);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteBlobIndex(records[i].HashValue);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(4)
+                               .WriteStringIndex()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+       }
+
+       sealed class ExportedTypeTable : Table<ExportedTypeTable.Record>
+       {
+               internal const int Index = 0x27;
+
+               internal struct Record
+               {
+                       internal int Flags;
+                       internal int TypeDefId;
+                       internal int TypeName;
+                       internal int TypeNamespace;
+                       internal int Implementation;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Flags = mr.ReadInt32();
+                               records[i].TypeDefId = mr.ReadInt32();
+                               records[i].TypeName = mr.ReadStringIndex();
+                               records[i].TypeNamespace = mr.ReadStringIndex();
+                               records[i].Implementation = mr.ReadImplementation();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Flags);
+                               mw.Write(records[i].TypeDefId);
+                               mw.WriteStringIndex(records[i].TypeName);
+                               mw.WriteStringIndex(records[i].TypeNamespace);
+                               mw.WriteImplementation(records[i].Implementation);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(8)
+                               .WriteStringIndex()
+                               .WriteStringIndex()
+                               .WriteImplementation()
+                               .Value;
+               }
+
+               internal int FindOrAddRecord(Record rec)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i].Implementation == rec.Implementation
+                                       && records[i].TypeName == rec.TypeName
+                                       && records[i].TypeNamespace == rec.TypeNamespace)
+                               {
+                                       return i + 1;
+                               }
+                       }
+                       return AddRecord(rec);
+               }
+       }
+
+       sealed class ManifestResourceTable : Table<ManifestResourceTable.Record>
+       {
+               internal const int Index = 0x28;
+
+               internal struct Record
+               {
+                       internal int Offset;
+                       internal int Flags;
+                       internal int Name;
+                       internal int Implementation;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Offset = mr.ReadInt32();
+                               records[i].Flags = mr.ReadInt32();
+                               records[i].Name = mr.ReadStringIndex();
+                               records[i].Implementation = mr.ReadImplementation();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Offset);
+                               mw.Write(records[i].Flags);
+                               mw.WriteStringIndex(records[i].Name);
+                               mw.WriteImplementation(records[i].Implementation);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(8)
+                               .WriteStringIndex()
+                               .WriteImplementation()
+                               .Value;
+               }
+       }
+
+       sealed class NestedClassTable : Table<NestedClassTable.Record>
+       {
+               internal const int Index = 0x29;
+
+               internal struct Record
+               {
+                       internal int NestedClass;
+                       internal int EnclosingClass;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].NestedClass = mr.ReadTypeDef();
+                               records[i].EnclosingClass = mr.ReadTypeDef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteTypeDef(records[i].NestedClass);
+                               mw.WriteTypeDef(records[i].EnclosingClass);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteTypeDef()
+                               .WriteTypeDef()
+                               .Value;
+               }
+
+               internal List<int> GetNestedClasses(int enclosingClass)
+               {
+                       List<int> nestedClasses = new List<int>();
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i].EnclosingClass == enclosingClass)
+                               {
+                                       nestedClasses.Add(records[i].NestedClass);
+                               }
+                       }
+                       return nestedClasses;
+               }
+       }
+
+       sealed class GenericParamTable : Table<GenericParamTable.Record>, IComparer<GenericParamTable.Record>
+       {
+               internal const int Index = 0x2A;
+
+               internal struct Record
+               {
+                       internal short Number;
+                       internal short Flags;
+                       internal int Owner;
+                       internal int Name;
+                       // not part of the table, we use it to be able to fixup the GenericParamConstraint table
+                       internal int unsortedIndex;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Number = mr.ReadInt16();
+                               records[i].Flags = mr.ReadInt16();
+                               records[i].Owner = mr.ReadTypeOrMethodDef();
+                               records[i].Name = mr.ReadStringIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.Write(records[i].Number);
+                               mw.Write(records[i].Flags);
+                               mw.WriteTypeOrMethodDef(records[i].Owner);
+                               mw.WriteStringIndex(records[i].Name);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .AddFixed(4)
+                               .WriteTypeOrMethodDef()
+                               .WriteStringIndex()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               int token = records[i].Owner;
+                               if (moduleBuilder.IsPseudoToken(token))
+                               {
+                                       token = moduleBuilder.ResolvePseudoToken(token);
+                               }
+                               // do the TypeOrMethodDef encoding, so that we can sort the table
+                               switch (token >> 24)
+                               {
+                                       case TypeDefTable.Index:
+                                               records[i].Owner = (token & 0xFFFFFF) << 1 | 0;
+                                               break;
+                                       case MethodDefTable.Index:
+                                               records[i].Owner = (token & 0xFFFFFF) << 1 | 1;
+                                               break;
+                                       default:
+                                               throw new InvalidOperationException();
+                               }
+                               records[i].unsortedIndex = i;
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       if (x.Owner == y.Owner)
+                       {
+                               return x.Number == y.Number ? 0 : (x.Number > y.Number ? 1 : -1);
+                       }
+                       return x.Owner > y.Owner ? 1 : -1;
+               }
+
+               internal GenericParameterAttributes GetAttributes(int token)
+               {
+                       return (GenericParameterAttributes)records[(token & 0xFFFFFF) - 1].Flags;
+               }
+
+               internal void PatchAttribute(int token, GenericParameterAttributes genericParameterAttributes)
+               {
+                       records[(token & 0xFFFFFF) - 1].Flags = (short)genericParameterAttributes;
+               }
+
+               internal int[] GetIndexFixup()
+               {
+                       int[] array = new int[rowCount];
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               array[records[i].unsortedIndex] = i;
+                       }
+                       return array;
+               }
+
+               internal int FindFirstByOwner(int token)
+               {
+                       // TODO use binary search (if sorted)
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               if (records[i].Owner == token)
+                               {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               }
+       }
+
+       sealed class MethodSpecTable : Table<MethodSpecTable.Record>
+       {
+               internal const int Index = 0x2B;
+
+               internal struct Record
+               {
+                       internal int Method;
+                       internal int Instantiation;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Method = mr.ReadMethodDefOrRef();
+                               records[i].Instantiation = mr.ReadBlobIndex();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteMethodDefOrRef(records[i].Method);
+                               mw.WriteBlobIndex(records[i].Instantiation);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteMethodDefOrRef()
+                               .WriteBlobIndex()
+                               .Value;
+               }
+
+               internal int FindOrAddRecord(Record record)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (records[i].Method == record.Method
+                                       && records[i].Instantiation == record.Instantiation)
+                               {
+                                       return i + 1;
+                               }
+                       }
+                       return AddRecord(record);
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               if (moduleBuilder.IsPseudoToken(records[i].Method))
+                               {
+                                       records[i].Method = moduleBuilder.ResolvePseudoToken(records[i].Method);
+                               }
+                       }
+               }
+       }
+
+       sealed class GenericParamConstraintTable : Table<GenericParamConstraintTable.Record>, IComparer<GenericParamConstraintTable.Record>
+       {
+               internal const int Index = 0x2C;
+
+               internal struct Record
+               {
+                       internal int Owner;
+                       internal int Constraint;
+               }
+
+               internal override void Read(MetadataReader mr)
+               {
+                       for (int i = 0; i < records.Length; i++)
+                       {
+                               records[i].Owner = mr.ReadGenericParam();
+                               records[i].Constraint = mr.ReadTypeDefOrRef();
+                       }
+               }
+
+               internal override void Write(MetadataWriter mw)
+               {
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               mw.WriteGenericParam(records[i].Owner);
+                               mw.WriteTypeDefOrRef(records[i].Constraint);
+                       }
+               }
+
+               protected override int GetRowSize(RowSizeCalc rsc)
+               {
+                       return rsc
+                               .WriteGenericParam()
+                               .WriteTypeDefOrRef()
+                               .Value;
+               }
+
+               internal void Fixup(ModuleBuilder moduleBuilder)
+               {
+                       int[] fixups = moduleBuilder.GenericParam.GetIndexFixup();
+                       for (int i = 0; i < rowCount; i++)
+                       {
+                               records[i].Owner = fixups[records[i].Owner - 1] + 1;
+                       }
+                       Array.Sort(records, 0, rowCount, this);
+               }
+
+               int IComparer<Record>.Compare(Record x, Record y)
+               {
+                       return x.Owner == y.Owner ? 0 : (x.Owner > y.Owner ? 1 : -1);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MethodBase.cs b/mcs/class/IKVM.Reflection/MethodBase.cs
new file mode 100644 (file)
index 0000000..b7e4b85
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+       public abstract class MethodBase : MemberInfo
+       {
+               internal abstract MethodSignature MethodSignature { get; }
+               internal abstract int ParameterCount { get; }
+               public abstract ParameterInfo[] GetParameters();
+               public abstract MethodAttributes Attributes { get; }
+               public abstract MethodImplAttributes GetMethodImplementationFlags();
+               public abstract MethodBody GetMethodBody();
+               public abstract CallingConventions CallingConvention { get; }
+
+               public bool IsConstructor
+               {
+                       get
+                       {
+                               if ((this.Attributes & MethodAttributes.RTSpecialName) != 0)
+                               {
+                                       string name = this.Name;
+                                       return name == ConstructorInfo.ConstructorName || name == ConstructorInfo.TypeConstructorName;
+                               }
+                               return false;
+                       }
+               }
+
+               public bool IsStatic
+               {
+                       get { return (Attributes & MethodAttributes.Static) != 0; }
+               }
+
+               public bool IsVirtual
+               {
+                       get { return (Attributes & MethodAttributes.Virtual) != 0; }
+               }
+
+               public bool IsAbstract
+               {
+                       get { return (Attributes & MethodAttributes.Abstract) != 0; }
+               }
+
+               public bool IsFinal
+               {
+                       get { return (Attributes & MethodAttributes.Final) != 0; }
+               }
+
+               public bool IsPublic
+               {
+                       get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; }
+               }
+
+               public bool IsFamily
+               {
+                       get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; }
+               }
+
+               public bool IsFamilyOrAssembly
+               {
+                       get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; }
+               }
+
+               public bool IsAssembly
+               {
+                       get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; }
+               }
+
+               public bool IsFamilyAndAssembly
+               {
+                       get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; }
+               }
+
+               public bool IsPrivate
+               {
+                       get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; }
+               }
+
+               public bool IsSpecialName
+               {
+                       get { return (Attributes & MethodAttributes.SpecialName) != 0; }
+               }
+
+               public bool IsHideBySig
+               {
+                       get { return (Attributes & MethodAttributes.HideBySig) != 0; }
+               }
+
+               public virtual Type[] GetGenericArguments()
+               {
+                       return Type.EmptyTypes;
+               }
+
+               public virtual bool IsGenericMethod
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsGenericMethodDefinition
+               {
+                       get { return false; }
+               }
+
+               public virtual bool ContainsGenericParameters
+               {
+                       get { return IsGenericMethodDefinition; }
+               }
+
+               // This goes to the (uninstantiated) MethodInfo on the (uninstantiated) Type. For constructors
+               // it also has the effect of removing the ConstructorInfo wrapper and returning the underlying MethodInfo.
+               internal abstract MethodInfo GetMethodOnTypeDefinition();
+
+               internal abstract int ImportTo(Emit.ModuleBuilder module);
+
+               internal abstract MethodBase BindTypeParameters(Type type);
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MethodBody.cs b/mcs/class/IKVM.Reflection/MethodBody.cs
new file mode 100644 (file)
index 0000000..7e14992
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using IKVM.Reflection.Reader;
+using System.IO;
+
+namespace IKVM.Reflection
+{
+       public sealed class MethodBody
+       {
+               private readonly IList<ExceptionHandlingClause> exceptionClauses;
+               private readonly IList<LocalVariableInfo> locals;
+               private readonly bool initLocals;
+               private readonly int maxStack;
+               private readonly int localVarSigTok;
+               private byte[] body;
+
+               internal MethodBody(ModuleReader module, int rva, IGenericContext context)
+               {
+                       const byte CorILMethod_TinyFormat = 0x02;
+                       const byte CorILMethod_FatFormat = 0x03;
+                       const byte CorILMethod_MoreSects = 0x08;
+                       const byte CorILMethod_InitLocals = 0x10;
+                       const byte CorILMethod_Sect_EHTable = 0x01;
+                       const byte CorILMethod_Sect_FatFormat = 0x40;
+                       const byte CorILMethod_Sect_MoreSects = 0x80;
+
+                       List<ExceptionHandlingClause> exceptionClauses = new List<ExceptionHandlingClause>();
+                       List<LocalVariableInfo> locals = new List<LocalVariableInfo>();
+                       module.SeekRVA(rva);
+                       BinaryReader br = new BinaryReader(module.stream);
+                       byte b = br.ReadByte();
+                       if ((b & 3) == CorILMethod_TinyFormat)
+                       {
+                               initLocals = true;
+                               body = br.ReadBytes(b >> 2);
+                       }
+                       else if ((b & 3) == CorILMethod_FatFormat)
+                       {
+                               initLocals = (b & CorILMethod_InitLocals) != 0;
+                               short flagsAndSize = (short)(b | (br.ReadByte() << 8));
+                               if ((flagsAndSize >> 12) != 3)
+                               {
+                                       throw new BadImageFormatException("Fat format method header size should be 3");
+                               }
+                               maxStack = br.ReadUInt16();
+                               int codeLength = br.ReadInt32();
+                               localVarSigTok = br.ReadInt32();
+                               body = br.ReadBytes(codeLength);
+                               if ((b & CorILMethod_MoreSects) != 0)
+                               {
+                                       module.stream.Position = (module.stream.Position + 3) & ~3;
+                                       int hdr = br.ReadInt32();
+                                       if ((hdr & CorILMethod_Sect_MoreSects) != 0 || (hdr & CorILMethod_Sect_EHTable) == 0)
+                                       {
+                                               throw new NotImplementedException();
+                                       }
+                                       else if ((hdr & CorILMethod_Sect_FatFormat) != 0)
+                                       {
+                                               int count = ComputeExceptionCount((hdr >> 8) & 0xFFFFFF, 24);
+                                               for (int i = 0; i < count; i++)
+                                               {
+                                                       int flags = br.ReadInt32();
+                                                       int tryOffset = br.ReadInt32();
+                                                       int tryLength = br.ReadInt32();
+                                                       int handlerOffset = br.ReadInt32();
+                                                       int handlerLength = br.ReadInt32();
+                                                       int classTokenOrFilterOffset = br.ReadInt32();
+                                                       exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               int count = ComputeExceptionCount((hdr >> 8) & 0xFF, 12);
+                                               for (int i = 0; i < count; i++)
+                                               {
+                                                       int flags = br.ReadUInt16();
+                                                       int tryOffset = br.ReadUInt16();
+                                                       int tryLength = br.ReadByte();
+                                                       int handlerOffset = br.ReadUInt16();
+                                                       int handlerLength = br.ReadByte();
+                                                       int classTokenOrFilterOffset = br.ReadInt32();
+                                                       exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
+                                               }
+                                       }
+                               }
+                               if (localVarSigTok != 0)
+                               {
+                                       ByteReader sig = module.ResolveSignature(localVarSigTok);
+                                       Signature.ReadLocalVarSig(module, sig, context, locals);
+                               }
+                       }
+                       else
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       this.exceptionClauses = exceptionClauses.AsReadOnly();
+                       this.locals = locals.AsReadOnly();
+               }
+
+               private static int ComputeExceptionCount(int size, int itemLength)
+               {
+                       // LAMESPEC according to the spec, the count should be calculated as "(size - 4) / itemLength",
+                       // FXBUG but to workaround a VB compiler bug that specifies the size incorrectly,
+                       // we do a truncating division instead.
+                       return size / itemLength;
+               }
+
+               public IList<ExceptionHandlingClause> ExceptionHandlingClauses
+               {
+                       get { return exceptionClauses; }
+               }
+
+               public bool InitLocals
+               {
+                       get { return initLocals; }
+               }
+
+               public IList<LocalVariableInfo> LocalVariables
+               {
+                       get { return locals; }
+               }
+
+               public byte[] GetILAsByteArray()
+               {
+                       return body;
+               }
+
+               public int LocalSignatureMetadataToken
+               {
+                       get { return localVarSigTok; }
+               }
+
+               public int MaxStackSize
+               {
+                       get { return maxStack; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MethodImplMap.cs b/mcs/class/IKVM.Reflection/MethodImplMap.cs
new file mode 100644 (file)
index 0000000..bab829f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       public struct __MethodImplMap
+       {
+               public Type TargetType;
+               public MethodInfo[] MethodBodies;
+               public MethodInfo[][] MethodDeclarations;
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MethodInfo.cs b/mcs/class/IKVM.Reflection/MethodInfo.cs
new file mode 100644 (file)
index 0000000..6d8e997
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       public abstract class MethodInfo : MethodBase, IGenericContext, IGenericBinder
+       {
+               public sealed override MemberTypes MemberType
+               {
+                       get { return MemberTypes.Method; }
+               }
+
+               public abstract Type ReturnType { get; }
+               public abstract ParameterInfo ReturnParameter { get; }
+
+               public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments)
+               {
+                       throw new NotSupportedException(this.GetType().FullName);
+               }
+
+               public virtual MethodInfo GetGenericMethodDefinition()
+               {
+                       throw new NotSupportedException(this.GetType().FullName);
+               }
+
+               public override string ToString()
+               {
+                       StringBuilder sb = new StringBuilder();
+                       sb.Append(this.ReturnType.Name).Append(' ').Append(this.Name);
+                       string sep;
+                       if (this.IsGenericMethod)
+                       {
+                               sb.Append('[');
+                               sep = "";
+                               foreach (Type arg in GetGenericArguments())
+                               {
+                                       sb.Append(sep).Append(arg);
+                                       sep = ", ";
+                               }
+                               sb.Append(']');
+                       }
+                       sb.Append('(');
+                       sep = "";
+                       foreach (ParameterInfo arg in GetParameters())
+                       {
+                               sb.Append(sep).Append(arg.ParameterType);
+                               sep = ", ";
+                       }
+                       sb.Append(')');
+                       return sb.ToString();
+               }
+
+               internal bool IsNewSlot
+               {
+                       get { return (this.Attributes & MethodAttributes.NewSlot) != 0; }
+               }
+
+               public MethodInfo GetBaseDefinition()
+               {
+                       MethodInfo match = this;
+                       if (match.IsVirtual)
+                       {
+                               for (Type type = this.DeclaringType.BaseType; type != null && !match.IsNewSlot; type = type.BaseType)
+                               {
+                                       MethodInfo method = type.FindMethod(this.Name, this.MethodSignature) as MethodInfo;
+                                       if (method != null && method.IsVirtual)
+                                       {
+                                               match = method;
+                                       }
+                               }
+                       }
+                       return match;
+               }
+
+               Type IGenericContext.GetGenericTypeArgument(int index)
+               {
+                       return this.DeclaringType.GetGenericTypeArgument(index);
+               }
+
+               Type IGenericContext.GetGenericMethodArgument(int index)
+               {
+                       return GetGenericMethodArgument(index);
+               }
+
+               internal virtual Type GetGenericMethodArgument(int index)
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal virtual int GetGenericMethodArgumentCount()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal override MethodInfo GetMethodOnTypeDefinition()
+               {
+                       return this;
+               }
+
+               Type IGenericBinder.BindTypeParameter(Type type)
+               {
+                       return this.DeclaringType.GetGenericTypeArgument(type.GenericParameterPosition);
+               }
+
+               Type IGenericBinder.BindMethodParameter(Type type)
+               {
+                       return GetGenericMethodArgument(type.GenericParameterPosition);
+               }
+
+               internal override MethodBase BindTypeParameters(Type type)
+               {
+                       return new GenericMethodInstance(this.DeclaringType.BindTypeParameters(type), this, null);
+               }
+
+               // This method is used by ILGenerator and exists to allow ArrayMethod to override it,
+               // because ArrayMethod doesn't have a working MethodAttributes property, so it needs
+               // to base the result of this on the CallingConvention.
+               internal virtual bool HasThis
+               {
+                       get { return !IsStatic; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/MethodSignature.cs b/mcs/class/IKVM.Reflection/MethodSignature.cs
new file mode 100644 (file)
index 0000000..8db04bc
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection
+{
+       sealed class MethodSignature : Signature
+       {
+               private readonly Type returnType;
+               private readonly Type[] parameterTypes;
+               private readonly Type[][][] modifiers;  // see PackedCustomModifiers
+               private readonly CallingConventions callingConvention;
+               private readonly int genericParamCount;
+
+               private MethodSignature(Type returnType, Type[] parameterTypes, Type[][][] modifiers, CallingConventions callingConvention, int genericParamCount)
+               {
+                       this.returnType = returnType;
+                       this.parameterTypes = parameterTypes;
+                       this.modifiers = modifiers;
+                       this.callingConvention = callingConvention;
+                       this.genericParamCount = genericParamCount;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       MethodSignature other = obj as MethodSignature;
+                       return other != null
+                               && other.callingConvention == callingConvention
+                               && other.genericParamCount == genericParamCount
+                               && other.returnType.Equals(returnType)
+                               && Util.ArrayEquals(other.parameterTypes, parameterTypes)
+                               && Util.ArrayEquals(other.modifiers, modifiers);
+               }
+
+               public override int GetHashCode()
+               {
+                       return genericParamCount ^ 77 * (int)callingConvention
+                               ^ 3 * returnType.GetHashCode()
+                               ^ Util.GetHashCode(parameterTypes) * 5
+                               ^ Util.GetHashCode(modifiers) * 55;
+               }
+
+               private sealed class UnboundGenericMethodContext : IGenericContext
+               {
+                       private readonly IGenericContext original;
+
+                       internal UnboundGenericMethodContext(IGenericContext original)
+                       {
+                               this.original = original;
+                       }
+
+                       public Type GetGenericTypeArgument(int index)
+                       {
+                               return original.GetGenericTypeArgument(index);
+                       }
+
+                       public Type GetGenericMethodArgument(int index)
+                       {
+                               return UnboundGenericMethodParameter.Make(index);
+                       }
+               }
+
+               internal static MethodSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       CallingConventions callingConvention;
+                       int genericParamCount;
+                       Type returnType;
+                       Type[] parameterTypes;
+                       byte flags = br.ReadByte();
+                       switch (flags & 7)
+                       {
+                               case DEFAULT:
+                                       callingConvention = CallingConventions.Standard;
+                                       break;
+                               case VARARG:
+                                       callingConvention = CallingConventions.VarArgs;
+                                       break;
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+                       if ((flags & HASTHIS) != 0)
+                       {
+                               callingConvention |= CallingConventions.HasThis;
+                       }
+                       if ((flags & EXPLICITTHIS) != 0)
+                       {
+                               callingConvention |= CallingConventions.ExplicitThis;
+                       }
+                       genericParamCount = 0;
+                       if ((flags & GENERIC) != 0)
+                       {
+                               genericParamCount = br.ReadCompressedInt();
+                               context = new UnboundGenericMethodContext(context);
+                       }
+                       int paramCount = br.ReadCompressedInt();
+                       Type[][][] modifiers = null;
+                       Type[] optionalCustomModifiers;
+                       Type[] requiredCustomModifiers;
+                       ReadCustomModifiers(module, br, context, out requiredCustomModifiers, out optionalCustomModifiers);
+                       returnType = ReadRetType(module, br, context);
+                       parameterTypes = new Type[paramCount];
+                       PackedCustomModifiers.SetModifiers(ref modifiers, 0, 0, optionalCustomModifiers, paramCount + 1);
+                       PackedCustomModifiers.SetModifiers(ref modifiers, 0, 1, requiredCustomModifiers, paramCount + 1);
+                       for (int i = 0; i < parameterTypes.Length; i++)
+                       {
+                               if ((callingConvention & CallingConventions.VarArgs) != 0 && br.PeekByte() == SENTINEL)
+                               {
+                                       Array.Resize(ref parameterTypes, i);
+                                       if (modifiers != null)
+                                       {
+                                               Array.Resize(ref modifiers, i + 1);
+                                       }
+                                       break;
+                               }
+                               ReadCustomModifiers(module, br, context, out requiredCustomModifiers, out optionalCustomModifiers);
+                               PackedCustomModifiers.SetModifiers(ref modifiers, i + 1, 0, optionalCustomModifiers, paramCount + 1);
+                               PackedCustomModifiers.SetModifiers(ref modifiers, i + 1, 1, requiredCustomModifiers, paramCount + 1);
+                               parameterTypes[i] = ReadParam(module, br, context);
+                       }
+                       return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount);
+               }
+
+               internal static __StandAloneMethodSig ReadStandAloneMethodSig(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       CallingConventions callingConvention = 0;
+                       System.Runtime.InteropServices.CallingConvention unmanagedCallingConvention = 0;
+                       bool unmanaged;
+                       byte flags = br.ReadByte();
+                       switch (flags & 7)
+                       {
+                               case DEFAULT:
+                                       callingConvention = CallingConventions.Standard;
+                                       unmanaged = false;
+                                       break;
+                               case 0x01:      // C
+                                       unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
+                                       unmanaged = true;
+                                       break;
+                               case 0x02:      // STDCALL
+                                       unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
+                                       unmanaged = true;
+                                       break;
+                               case 0x03:      // THISCALL
+                                       unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
+                                       unmanaged = true;
+                                       break;
+                               case 0x04:      // FASTCALL
+                                       unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
+                                       unmanaged = true;
+                                       break;
+                               case VARARG:
+                                       callingConvention = CallingConventions.VarArgs;
+                                       unmanaged = false;
+                                       break;
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+                       if ((flags & HASTHIS) != 0)
+                       {
+                               callingConvention |= CallingConventions.HasThis;
+                       }
+                       if ((flags & EXPLICITTHIS) != 0)
+                       {
+                               callingConvention |= CallingConventions.ExplicitThis;
+                       }
+                       if ((flags & GENERIC) != 0)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       int paramCount = br.ReadCompressedInt();
+                       SkipCustomModifiers(br);
+                       Type returnType = ReadRetType(module, br, context);
+                       List<Type> parameterTypes = new List<Type>();
+                       List<Type> optionalParameterTypes = new List<Type>();
+                       List<Type> curr = parameterTypes;
+                       for (int i = 0; i < paramCount; i++)
+                       {
+                               if (br.PeekByte() == SENTINEL)
+                               {
+                                       br.ReadByte();
+                                       curr = optionalParameterTypes;
+                               }
+                               SkipCustomModifiers(br);
+                               curr.Add(ReadParam(module, br, context));
+                       }
+                       return new __StandAloneMethodSig(unmanaged, unmanagedCallingConvention, callingConvention, returnType, parameterTypes.ToArray(), optionalParameterTypes.ToArray());
+               }
+
+               internal int GetParameterCount()
+               {
+                       return parameterTypes.Length;
+               }
+
+               internal Type GetParameterType(int index)
+               {
+                       return parameterTypes[index];
+               }
+
+               internal Type GetReturnType(IGenericBinder binder)
+               {
+                       return returnType.BindTypeParameters(binder);
+               }
+
+               internal Type[] GetReturnTypeOptionalCustomModifiers(IGenericBinder binder)
+               {
+                       return BindTypeParameters(binder, modifiers, 0, 0);
+               }
+
+               internal Type[] GetReturnTypeRequiredCustomModifiers(IGenericBinder binder)
+               {
+                       return BindTypeParameters(binder, modifiers, 0, 1);
+               }
+
+               internal Type GetParameterType(IGenericBinder binder, int index)
+               {
+                       return parameterTypes[index].BindTypeParameters(binder);
+               }
+
+               internal Type[] GetParameterOptionalCustomModifiers(IGenericBinder binder, int index)
+               {
+                       return BindTypeParameters(binder, modifiers, index + 1, 0);
+               }
+
+               internal Type[] GetParameterRequiredCustomModifiers(IGenericBinder binder, int index)
+               {
+                       return BindTypeParameters(binder, modifiers, index + 1, 1);
+               }
+
+               internal CallingConventions CallingConvention
+               {
+                       get { return callingConvention; }
+               }
+
+               private sealed class Binder : IGenericBinder
+               {
+                       private readonly Type declaringType;
+                       private readonly Type[] methodArgs;
+
+                       internal Binder(Type declaringType, Type[] methodArgs)
+                       {
+                               this.declaringType = declaringType;
+                               this.methodArgs = methodArgs;
+                       }
+
+                       public Type BindTypeParameter(Type type)
+                       {
+                               return declaringType.GetGenericTypeArgument(type.GenericParameterPosition);
+                       }
+
+                       public Type BindMethodParameter(Type type)
+                       {
+                               if (methodArgs == null)
+                               {
+                                       return type;
+                               }
+                               return methodArgs[type.GenericParameterPosition];
+                       }
+               }
+
+               internal MethodSignature Bind(Type type, Type[] methodArgs)
+               {
+                       Binder binder = new Binder(type, methodArgs);
+                       return new MethodSignature(returnType.BindTypeParameters(binder),
+                               BindTypeParameters(binder, parameterTypes),
+                               BindTypeParameters(binder, modifiers),
+                               callingConvention, genericParamCount);
+               }
+
+               private sealed class Unbinder : IGenericBinder
+               {
+                       internal static readonly Unbinder Instance = new Unbinder();
+
+                       private Unbinder()
+                       {
+                       }
+
+                       public Type BindTypeParameter(Type type)
+                       {
+                               return type;
+                       }
+
+                       public Type BindMethodParameter(Type type)
+                       {
+                               return UnboundGenericMethodParameter.Make(type.GenericParameterPosition);
+                       }
+               }
+
+               internal static MethodSignature MakeFromBuilder(Type returnType, Type[] parameterTypes, Type[][][] modifiers, CallingConventions callingConvention, int genericParamCount)
+               {
+                       if (genericParamCount > 0)
+                       {
+                               returnType = returnType.BindTypeParameters(Unbinder.Instance);
+                               parameterTypes = BindTypeParameters(Unbinder.Instance, parameterTypes);
+                               modifiers = BindTypeParameters(Unbinder.Instance, modifiers);
+                       }
+                       return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount);
+               }
+
+               internal bool MatchParameterTypes(Type[] types)
+               {
+                       if (types == parameterTypes)
+                       {
+                               return true;
+                       }
+                       if (types == null)
+                       {
+                               return parameterTypes.Length == 0;
+                       }
+                       if (parameterTypes == null)
+                       {
+                               return types.Length == 0;
+                       }
+                       if (types.Length == parameterTypes.Length)
+                       {
+                               for (int i = 0; i < types.Length; i++)
+                               {
+                                       if (!Util.TypeEquals(types[i], parameterTypes[i]))
+                                       {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
+               {
+                       WriteSigImpl(module, bb, parameterTypes.Length);
+               }
+
+               internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes)
+               {
+                       WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length);
+                       if (optionalParameterTypes.Length > 0)
+                       {
+                               bb.Write(SENTINEL);
+                               foreach (Type type in optionalParameterTypes)
+                               {
+                                       WriteType(module, bb, type);
+                               }
+                       }
+               }
+
+               private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount)
+               {
+                       byte first;
+                       if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs)
+                       {
+                               Debug.Assert(genericParamCount == 0);
+                               first = VARARG;
+                       }
+                       else if (genericParamCount > 0)
+                       {
+                               first = GENERIC;
+                       }
+                       else
+                       {
+                               first = DEFAULT;
+                       }
+                       if ((callingConvention & CallingConventions.HasThis) != 0)
+                       {
+                               first |= HASTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+                       {
+                               first |= EXPLICITTHIS;
+                       }
+                       bb.Write(first);
+                       if (genericParamCount > 0)
+                       {
+                               bb.WriteCompressedInt(genericParamCount);
+                       }
+                       bb.WriteCompressedInt(parameterCount);
+                       // RetType
+                       if (modifiers != null && modifiers[0] != null)
+                       {
+                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[0][0]);
+                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[0][1]);
+                       }
+                       WriteType(module, bb, returnType);
+                       // Param
+                       for (int i = 0; i < parameterTypes.Length; i++)
+                       {
+                               if (modifiers != null && modifiers[i + 1] != null)
+                               {
+                                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[i + 1][0]);
+                                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[i + 1][1]);
+                               }
+                               WriteType(module, bb, parameterTypes[i]);
+                       }
+               }
+       }
+
+       static class PackedCustomModifiers
+       {
+               // modifiers are packed in a very specific way (and required to be so, otherwise equality checks will fail)
+               // For modifiers[x][y][z]:
+               //  x = parameter index, 0 = return type, 1 = first parameters, ...
+               //  y = 0 = optional custom modifiers, 1 = required custom modifiers
+               //  z = the custom modifiers
+               // At any level the reference can be null (and *must* be null, if there are no modifiers below that level).
+               // Empty arrays are not allowed at any level.
+
+               // this can be used to "add" elements to the modifiers array (and the elements are assumed to already be in normalized form)
+               internal static void SetModifiers(ref Type[][][] modifiers, int index, int optOrReq, Type[] add, int count)
+               {
+                       if (add != null)
+                       {
+                               if (modifiers == null)
+                               {
+                                       modifiers = new Type[count][][];
+                               }
+                               if (modifiers[index] == null)
+                               {
+                                       modifiers[index] = new Type[2][];
+                               }
+                               modifiers[index][optOrReq] = add;
+                       }
+               }
+
+               // this method make a copy of the incoming arrays (where necessary) and returns a normalized modifiers array
+               internal static Type[][][] CreateFromExternal(Type[] returnOptional, Type[] returnRequired, Type[][] parameterOptional, Type[][] parameterRequired, int parameterCount)
+               {
+                       Type[][][] modifiers = null;
+                       SetModifiers(ref modifiers, 0, 0, NormalizeAndCopy(returnOptional), parameterCount + 1);
+                       SetModifiers(ref modifiers, 0, 1, NormalizeAndCopy(returnRequired), parameterCount + 1);
+                       for (int i = 0; i < parameterCount; i++)
+                       {
+                               SetModifiers(ref modifiers, i + 1, 0, NormalizeAndCopy(parameterOptional, i), parameterCount + 1);
+                               SetModifiers(ref modifiers, i + 1, 1, NormalizeAndCopy(parameterRequired, i), parameterCount + 1);
+                       }
+                       return modifiers;
+               }
+
+               private static Type[] NormalizeAndCopy(Type[] array)
+               {
+                       if (array == null || array.Length == 0)
+                       {
+                               return null;
+                       }
+                       Type[] copy = null;
+                       for (int i = 0; i < array.Length; i++)
+                       {
+                               if (array[i] != null)
+                               {
+                                       if (copy == null)
+                                       {
+                                               copy = new Type[array.Length];
+                                       }
+                                       copy[i] = array[i];
+                               }
+                       }
+                       return copy;
+               }
+
+               private static Type[] NormalizeAndCopy(Type[][] array, int index)
+               {
+                       if (array == null || array.Length == 0)
+                       {
+                               return null;
+                       }
+                       return NormalizeAndCopy(array[index]);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Module.cs b/mcs/class/IKVM.Reflection/Module.cs
new file mode 100644 (file)
index 0000000..a481ae2
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+       public sealed class RawModule : IDisposable
+       {
+               private readonly ModuleReader module;
+               private readonly bool isManifestModule;
+               private bool imported;
+
+               internal RawModule(ModuleReader module)
+               {
+                       this.module = module;
+                       this.isManifestModule = module.Assembly != null;
+               }
+
+               public string Location
+               {
+                       get { return module.FullyQualifiedName; }
+               }
+
+               public bool IsManifestModule
+               {
+                       get { return isManifestModule; }
+               }
+
+               private void CheckManifestModule()
+               {
+                       if (!IsManifestModule)
+                       {
+                               throw new BadImageFormatException("Module does not contain a manifest");
+                       }
+               }
+
+               public AssemblyName GetAssemblyName()
+               {
+                       CheckManifestModule();
+                       return module.Assembly.GetName();
+               }
+
+               public AssemblyName[] GetReferencedAssemblies()
+               {
+                       return module.__GetReferencedAssemblies();
+               }
+
+               public void Dispose()
+               {
+                       if (!imported)
+                       {
+                               module.stream.Dispose();
+                       }
+               }
+
+               internal Assembly ToAssembly()
+               {
+                       if (imported)
+                       {
+                               throw new InvalidOperationException();
+                       }
+                       imported = true;
+                       return module.Assembly;
+               }
+
+               internal Module ToModule(Assembly assembly)
+               {
+                       if (module.Assembly != null)
+                       {
+                               throw new InvalidOperationException();
+                       }
+                       imported = true;
+                       module.SetAssembly(assembly);
+                       return module;
+               }
+       }
+
+       public abstract class Module : ICustomAttributeProvider
+       {
+               internal readonly Universe universe;
+               internal readonly ModuleTable ModuleTable = new ModuleTable();
+               internal readonly TypeRefTable TypeRef = new TypeRefTable();
+               internal readonly TypeDefTable TypeDef = new TypeDefTable();
+               internal readonly FieldTable Field = new FieldTable();
+               internal readonly MemberRefTable MemberRef = new MemberRefTable();
+               internal readonly ConstantTable Constant = new ConstantTable();
+               internal readonly CustomAttributeTable CustomAttribute = new CustomAttributeTable();
+               internal readonly FieldMarshalTable FieldMarshal = new FieldMarshalTable();
+               internal readonly DeclSecurityTable DeclSecurity = new DeclSecurityTable();
+               internal readonly ClassLayoutTable ClassLayout = new ClassLayoutTable();
+               internal readonly FieldLayoutTable FieldLayout = new FieldLayoutTable();
+               internal readonly ParamTable Param = new ParamTable();
+               internal readonly InterfaceImplTable InterfaceImpl = new InterfaceImplTable();
+               internal readonly StandAloneSigTable StandAloneSig = new StandAloneSigTable();
+               internal readonly EventMapTable EventMap = new EventMapTable();
+               internal readonly EventTable Event = new EventTable();
+               internal readonly PropertyMapTable PropertyMap = new PropertyMapTable();
+               internal readonly PropertyTable Property = new PropertyTable();
+               internal readonly MethodSemanticsTable MethodSemantics = new MethodSemanticsTable();
+               internal readonly MethodImplTable MethodImpl = new MethodImplTable();
+               internal readonly ModuleRefTable ModuleRef = new ModuleRefTable();
+               internal readonly TypeSpecTable TypeSpec = new TypeSpecTable();
+               internal readonly ImplMapTable ImplMap = new ImplMapTable();
+               internal readonly FieldRVATable FieldRVA = new FieldRVATable();
+               internal readonly AssemblyTable AssemblyTable = new AssemblyTable();
+               internal readonly AssemblyRefTable AssemblyRef = new AssemblyRefTable();
+               internal readonly MethodDefTable MethodDef = new MethodDefTable();
+               internal readonly NestedClassTable NestedClass = new NestedClassTable();
+               internal readonly FileTable File = new FileTable();
+               internal readonly ExportedTypeTable ExportedType = new ExportedTypeTable();
+               internal readonly ManifestResourceTable ManifestResource = new ManifestResourceTable();
+               internal readonly GenericParamTable GenericParam = new GenericParamTable();
+               internal readonly MethodSpecTable MethodSpec = new MethodSpecTable();
+               internal readonly GenericParamConstraintTable GenericParamConstraint = new GenericParamConstraintTable();
+
+               internal Module(Universe universe)
+               {
+                       this.universe = universe;
+               }
+
+               internal Table[] GetTables()
+               {
+                       Table[] tables = new Table[64];
+                       tables[ModuleTable.Index] = ModuleTable;
+                       tables[TypeRefTable.Index] = TypeRef;
+                       tables[TypeDefTable.Index] = TypeDef;
+                       tables[FieldTable.Index] = Field;
+                       tables[MemberRefTable.Index] = MemberRef;
+                       tables[ConstantTable.Index] = Constant;
+                       tables[CustomAttributeTable.Index] = CustomAttribute;
+                       tables[FieldMarshalTable.Index] = FieldMarshal;
+                       tables[DeclSecurityTable.Index] = DeclSecurity;
+                       tables[ClassLayoutTable.Index] = ClassLayout;
+                       tables[FieldLayoutTable.Index] = FieldLayout;
+                       tables[ParamTable.Index] = Param;
+                       tables[InterfaceImplTable.Index] = InterfaceImpl;
+                       tables[StandAloneSigTable.Index] = StandAloneSig;
+                       tables[EventMapTable.Index] = EventMap;
+                       tables[EventTable.Index] = Event;
+                       tables[PropertyMapTable.Index] = PropertyMap;
+                       tables[PropertyTable.Index] = Property;
+                       tables[MethodSemanticsTable.Index] = MethodSemantics;
+                       tables[MethodImplTable.Index] = MethodImpl;
+                       tables[ModuleRefTable.Index] = ModuleRef;
+                       tables[TypeSpecTable.Index] = TypeSpec;
+                       tables[ImplMapTable.Index] = ImplMap;
+                       tables[FieldRVATable.Index] = FieldRVA;
+                       tables[AssemblyTable.Index] = AssemblyTable;
+                       tables[AssemblyRefTable.Index] = AssemblyRef;
+                       tables[MethodDefTable.Index] = MethodDef;
+                       tables[NestedClassTable.Index] = NestedClass;
+                       tables[FileTable.Index] = File;
+                       tables[ExportedTypeTable.Index] = ExportedType;
+                       tables[ManifestResourceTable.Index] = ManifestResource;
+                       tables[GenericParamTable.Index] = GenericParam;
+                       tables[MethodSpecTable.Index] = MethodSpec;
+                       tables[GenericParamConstraintTable.Index] = GenericParamConstraint;
+                       return tables;
+               }
+
+               public virtual void __GetDataDirectoryEntry(int index, out int rva, out int length)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public virtual long __RelativeVirtualAddressToFileOffset(int rva)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public virtual int __Subsystem
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public FieldInfo GetField(string name)
+               {
+                       return IsResource() ? null : GetModuleType().GetField(name);
+               }
+
+               public FieldInfo GetField(string name, BindingFlags bindingFlags)
+               {
+                       return IsResource() ? null : GetModuleType().GetField(name, bindingFlags);
+               }
+
+               public FieldInfo[] GetFields()
+               {
+                       return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields();
+               }
+
+               public FieldInfo[] GetFields(BindingFlags bindingFlags)
+               {
+                       return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields(bindingFlags);
+               }
+
+               public MethodInfo GetMethod(string name)
+               {
+                       return IsResource() ? null : GetModuleType().GetMethod(name);
+               }
+
+               public MethodInfo GetMethod(string name, Type[] types)
+               {
+                       return IsResource() ? null : GetModuleType().GetMethod(name, types);
+               }
+
+               public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers)
+               {
+                       return IsResource() ? null : GetModuleType().GetMethod(name, bindingAttr, binder, callConv, types, modifiers);
+               }
+
+               public MethodInfo[] GetMethods()
+               {
+                       return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods();
+               }
+
+               public MethodInfo[] GetMethods(BindingFlags bindingFlags)
+               {
+                       return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods(bindingFlags);
+               }
+
+               public ConstructorInfo __ModuleInitializer
+               {
+                       get { return IsResource() ? null : GetModuleType().TypeInitializer; }
+               }
+
+               public byte[] ResolveSignature(int metadataToken)
+               {
+                       ModuleReader rdr = this as ModuleReader;
+                       if (rdr != null)
+                       {
+                               ByteReader br = rdr.ResolveSignature(metadataToken);
+                               return br.ReadBytes(br.Length);
+                       }
+                       throw new NotSupportedException();
+               }
+
+               public virtual __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public int MetadataToken
+               {
+                       get { return IsResource() ? 0 : 1; }
+               }
+
+               public abstract int MDStreamVersion { get ;}
+               public abstract Assembly Assembly { get; }
+               public abstract string FullyQualifiedName { get; }
+               public abstract string Name { get; }
+               public abstract Guid ModuleVersionId { get; }
+               public abstract Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+               public abstract MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+               public abstract FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+               public abstract MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+
+               public abstract string ResolveString(int metadataToken);
+               public abstract Type[] __ResolveOptionalParameterTypes(int metadataToken);
+               public abstract string ScopeName { get; }
+
+               internal abstract Type GetTypeImpl(string typeName);
+               internal abstract void GetTypesImpl(List<Type> list);
+
+               public Type GetType(string className)
+               {
+                       return GetType(className, false, false);
+               }
+
+               public Type GetType(string className, bool ignoreCase)
+               {
+                       return GetType(className, false, ignoreCase);
+               }
+
+               public Type GetType(string className, bool throwOnError, bool ignoreCase)
+               {
+                       if (ignoreCase)
+                       {
+                               throw new NotImplementedException();
+                       }
+                       TypeNameParser parser = TypeNameParser.Parse(className, throwOnError);
+                       if (parser.Error)
+                       {
+                               return null;
+                       }
+                       if (parser.AssemblyName != null)
+                       {
+                               if (throwOnError)
+                               {
+                                       throw new ArgumentException("Type names passed to Module.GetType() must not specify an assembly.");
+                               }
+                               else
+                               {
+                                       return null;
+                               }
+                       }
+                       return parser.Expand(GetTypeImpl(parser.FirstNamePart), this.Assembly, throwOnError, className);
+               }
+
+               public Type[] GetTypes()
+               {
+                       List<Type> list = new List<Type>();
+                       GetTypesImpl(list);
+                       return list.ToArray();
+               }
+
+               public Type[] FindTypes(TypeFilter filter, object filterCriteria)
+               {
+                       List<Type> list = new List<Type>();
+                       foreach (Type type in GetTypes())
+                       {
+                               if (filter(type, filterCriteria))
+                               {
+                                       list.Add(type);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public virtual bool IsResource()
+               {
+                       return false;
+               }
+
+               public Type ResolveType(int metadataToken)
+               {
+                       return ResolveType(metadataToken, null, null);
+               }
+
+               public MethodBase ResolveMethod(int metadataToken)
+               {
+                       return ResolveMethod(metadataToken, null, null);
+               }
+
+               public FieldInfo ResolveField(int metadataToken)
+               {
+                       return ResolveField(metadataToken, null, null);
+               }
+
+               public MemberInfo ResolveMember(int metadataToken)
+               {
+                       return ResolveMember(metadataToken, null, null);
+               }
+
+               public bool IsDefined(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+               }
+
+               public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+               }
+
+               public virtual IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
+               {
+                       return Empty<CustomAttributeData>.Array;
+               }
+
+               public abstract AssemblyName[] __GetReferencedAssemblies();
+
+               internal Type CanonicalizeType(Type type)
+               {
+                       Type canon;
+                       if (!universe.canonicalizedTypes.TryGetValue(type, out canon))
+                       {
+                               canon = type;
+                               universe.canonicalizedTypes.Add(canon, canon);
+                       }
+                       return canon;
+               }
+
+               internal abstract Type GetModuleType();
+
+               internal abstract ByteReader GetBlob(int blobIndex);
+
+               internal IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return GetCustomAttributes(0x00000001, attributeType);
+               }
+
+               internal List<CustomAttributeData> GetCustomAttributes(int metadataToken, Type attributeType)
+               {
+                       List<CustomAttributeData> list = new List<CustomAttributeData>();
+                       // TODO use binary search?
+                       for (int i = 0; i < CustomAttribute.records.Length; i++)
+                       {
+                               if (CustomAttribute.records[i].Parent == metadataToken)
+                               {
+                                       if (attributeType == null)
+                                       {
+                                               list.Add(new CustomAttributeData(this, i));
+                                       }
+                                       else
+                                       {
+                                               ConstructorInfo constructor = (ConstructorInfo)ResolveMethod(CustomAttribute.records[i].Type);
+                                               if (attributeType.IsAssignableFrom(constructor.DeclaringType))
+                                               {
+                                                       list.Add(new CustomAttributeData(this.Assembly, constructor, GetBlob(CustomAttribute.records[i].Value)));
+                                               }
+                                       }
+                               }
+                       }
+                       return list;
+               }
+
+               internal IList<CustomAttributeData> GetDeclarativeSecurity(int metadataToken)
+               {
+                       List<CustomAttributeData> list = new List<CustomAttributeData>();
+                       // TODO use binary search?
+                       for (int i = 0; i < DeclSecurity.records.Length; i++)
+                       {
+                               if (DeclSecurity.records[i].Parent == metadataToken)
+                               {
+                                       int action = DeclSecurity.records[i].Action;
+                                       int permissionSet = DeclSecurity.records[i].PermissionSet;
+                                       CustomAttributeData.ReadDeclarativeSecurity(this.Assembly, list, action, GetBlob(permissionSet));
+                               }
+                       }
+                       return list;
+               }
+
+               internal virtual void Dispose()
+               {
+               }
+
+               internal virtual void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
+               {
+               }
+       }
+
+       public delegate bool TypeFilter(Type m, object filterCriteria);
+       public delegate bool MemberFilter(MemberInfo m, object filterCriteria);
+}
diff --git a/mcs/class/IKVM.Reflection/ParameterInfo.cs b/mcs/class/IKVM.Reflection/ParameterInfo.cs
new file mode 100644 (file)
index 0000000..6bc2fff
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System.Collections.Generic;
+
+namespace IKVM.Reflection
+{
+       public abstract class ParameterInfo : ICustomAttributeProvider
+       {
+               public sealed override bool Equals(object obj)
+               {
+                       ParameterInfo other = obj as ParameterInfo;
+                       return other != null && other.Member == this.Member && other.Position == this.Position;
+               }
+
+               public sealed override int GetHashCode()
+               {
+                       return this.Member.GetHashCode() * 1777 + this.Position;
+               }
+
+               public static bool operator ==(ParameterInfo p1, ParameterInfo p2)
+               {
+                       return ReferenceEquals(p1, p2) || (!ReferenceEquals(p1, null) && p1.Equals(p2));
+               }
+
+               public static bool operator !=(ParameterInfo p1, ParameterInfo p2)
+               {
+                       return !(p1 == p2);
+               }
+
+               public abstract string Name { get; }
+               public abstract Type ParameterType { get; }
+               public abstract ParameterAttributes Attributes { get; }
+               public abstract int Position { get; }
+               public abstract object RawDefaultValue { get; }
+               public abstract Type[] GetOptionalCustomModifiers();
+               public abstract Type[] GetRequiredCustomModifiers();
+               public abstract MemberInfo Member { get; }
+               public abstract int MetadataToken { get; }
+               internal abstract Module Module { get; }
+
+               public bool IsIn
+               {
+                       get { return (Attributes & ParameterAttributes.In) != 0; }
+               }
+
+               public bool IsOut
+               {
+                       get { return (Attributes & ParameterAttributes.Out) != 0; }
+               }
+
+               public bool IsLcid
+               {
+                       get { return (Attributes & ParameterAttributes.Lcid) != 0; }
+               }
+
+               public bool IsRetval
+               {
+                       get { return (Attributes & ParameterAttributes.Retval) != 0; }
+               }
+
+               public bool IsOptional
+               {
+                       get { return (Attributes & ParameterAttributes.Optional) != 0; }
+               }
+
+               public bool IsDefined(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+               }
+
+               public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+               {
+                       return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+               }
+
+               internal virtual IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return this.Module.GetCustomAttributes(this.MetadataToken, attributeType);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/ParameterModifier.cs b/mcs/class/IKVM.Reflection/ParameterModifier.cs
new file mode 100644 (file)
index 0000000..605cca4
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       public struct ParameterModifier
+       {
+               private readonly bool[] values;
+
+               public ParameterModifier(int parameterCount)
+               {
+                       values = new bool[parameterCount];
+               }
+
+               public bool this[int index]
+               {
+                       get { return values[index]; }
+                       set { values[index] = value; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Properties/AssemblyInfo.cs b/mcs/class/IKVM.Reflection/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..6422e19
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("IKVM.NET Reflection")]
+[assembly: AssemblyDescription("Managed (partial) Reflection implementation for use by ikvmc")]
diff --git a/mcs/class/IKVM.Reflection/PropertyInfo.cs b/mcs/class/IKVM.Reflection/PropertyInfo.cs
new file mode 100644 (file)
index 0000000..de991aa
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+       public abstract class PropertyInfo : MemberInfo
+       {
+               public sealed override MemberTypes MemberType
+               {
+                       get { return MemberTypes.Property; }
+               }
+
+               public abstract PropertyAttributes Attributes { get; }
+               public abstract bool CanRead { get; }
+               public abstract bool CanWrite { get; }
+               public abstract MethodInfo GetGetMethod(bool nonPublic);
+               public abstract MethodInfo GetSetMethod(bool nonPublic);
+               public abstract MethodInfo[] GetAccessors(bool nonPublic);
+               public abstract object GetRawConstantValue();
+               internal abstract bool IsPublic { get; }
+               internal abstract bool IsStatic { get; }
+               internal abstract PropertySignature PropertySignature { get; }
+
+               private sealed class ParameterInfoImpl : ParameterInfo
+               {
+                       private readonly PropertyInfo property;
+                       private readonly int parameter;
+
+                       internal ParameterInfoImpl(PropertyInfo property, int parameter)
+                       {
+                               this.property = property;
+                               this.parameter = parameter;
+                       }
+
+                       public override string Name
+                       {
+                               get { return null; }
+                       }
+
+                       public override Type ParameterType
+                       {
+                               get { return property.PropertySignature.GetParameter(parameter); }
+                       }
+
+                       public override ParameterAttributes Attributes
+                       {
+                               get { return ParameterAttributes.None; }
+                       }
+
+                       public override int Position
+                       {
+                               get { return parameter; }
+                       }
+
+                       public override object RawDefaultValue
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       public override Type[] GetOptionalCustomModifiers()
+                       {
+                               return property.PropertySignature.GetOptionalCustomModifiers(parameter);
+                       }
+
+                       public override Type[] GetRequiredCustomModifiers()
+                       {
+                               return property.PropertySignature.GetRequiredCustomModifiers(parameter);
+                       }
+
+                       public override MemberInfo Member
+                       {
+                               get { return property; }
+                       }
+
+                       public override int MetadataToken
+                       {
+                               get { return 0x08000000; }
+                       }
+
+                       internal override Module Module
+                       {
+                               get { return property.Module; }
+                       }
+               }
+
+               public ParameterInfo[] GetIndexParameters()
+               {
+                       ParameterInfo[] parameters = new ParameterInfo[this.PropertySignature.ParameterCount];
+                       for (int i = 0; i < parameters.Length; i++)
+                       {
+                               parameters[i] = new ParameterInfoImpl(this, i);
+                       }
+                       return parameters;
+               }
+
+               public Type PropertyType
+               {
+                       get { return this.PropertySignature.PropertyType; }
+               }
+
+               public Type[] GetRequiredCustomModifiers()
+               {
+                       return this.PropertySignature.GetRequiredCustomModifiers();
+               }
+
+               public Type[] GetOptionalCustomModifiers()
+               {
+                       return this.PropertySignature.GetOptionalCustomModifiers();
+               }
+
+               public bool IsSpecialName
+               {
+                       get { return (Attributes & PropertyAttributes.SpecialName) != 0; }
+               }
+
+               public MethodInfo GetGetMethod()
+               {
+                       return GetGetMethod(false);
+               }
+
+               public MethodInfo GetSetMethod()
+               {
+                       return GetSetMethod(false);
+               }
+
+               public MethodInfo[] GetAccessors()
+               {
+                       return GetAccessors(false);
+               }
+
+               internal virtual PropertyInfo BindTypeParameters(Type type)
+               {
+                       return new GenericPropertyInfo(this.DeclaringType.BindTypeParameters(type), this);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/PropertySignature.cs b/mcs/class/IKVM.Reflection/PropertySignature.cs
new file mode 100644 (file)
index 0000000..4e19dca
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+       sealed class PropertySignature : Signature
+       {
+               private CallingConventions callingConvention;
+               private readonly Type propertyType;
+               private readonly Type[] optionalCustomModifiers;
+               private readonly Type[] requiredCustomModifiers;
+               private readonly Type[] parameterTypes;
+               private readonly Type[][] parameterOptionalCustomModifiers;
+               private readonly Type[][] parameterRequiredCustomModifiers;
+
+               internal static PropertySignature Create(CallingConventions callingConvention, Type propertyType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeOptionalCustomModifiers, Type[][] parameterTypeRequiredCustomModifiers)
+               {
+                       return new PropertySignature(callingConvention, propertyType, Util.Copy(optionalCustomModifiers), Util.Copy(requiredCustomModifiers), Util.Copy(parameterTypes), Util.Copy(parameterTypeOptionalCustomModifiers), Util.Copy(parameterTypeRequiredCustomModifiers));
+               }
+
+               private PropertySignature(CallingConventions callingConvention, Type propertyType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeOptionalCustomModifiers, Type[][] parameterTypeRequiredCustomModifiers)
+               {
+                       this.callingConvention = callingConvention;
+                       this.propertyType = propertyType;
+                       this.optionalCustomModifiers = optionalCustomModifiers;
+                       this.requiredCustomModifiers = requiredCustomModifiers;
+                       this.parameterTypes = parameterTypes;
+                       this.parameterOptionalCustomModifiers = parameterTypeOptionalCustomModifiers;
+                       this.parameterRequiredCustomModifiers = parameterTypeRequiredCustomModifiers;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       PropertySignature other = obj as PropertySignature;
+                       return other != null
+                               && other.propertyType.Equals(propertyType)
+                               && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers)
+                               && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers);
+               }
+
+               public override int GetHashCode()
+               {
+                       return propertyType.GetHashCode() ^ Util.GetHashCode(optionalCustomModifiers) ^ Util.GetHashCode(requiredCustomModifiers);
+               }
+
+               internal int ParameterCount
+               {
+                       get { return parameterTypes.Length; }
+               }
+
+               internal bool HasThis
+               {
+                       set
+                       {
+                               if (value)
+                               {
+                                       callingConvention |= CallingConventions.HasThis;
+                               }
+                               else
+                               {
+                                       callingConvention &= ~CallingConventions.HasThis;
+                               }
+                       }
+               }
+
+               internal Type PropertyType
+               {
+                       get { return propertyType; }
+               }
+
+               internal Type[] GetOptionalCustomModifiers()
+               {
+                       return Util.Copy(optionalCustomModifiers);
+               }
+
+               internal Type[] GetRequiredCustomModifiers()
+               {
+                       return Util.Copy(requiredCustomModifiers);
+               }
+
+               internal PropertySignature ExpandTypeParameters(Type declaringType)
+               {
+                       return new PropertySignature(
+                               callingConvention,
+                               propertyType.BindTypeParameters(declaringType),
+                               BindTypeParameters(declaringType, optionalCustomModifiers),
+                               BindTypeParameters(declaringType, requiredCustomModifiers),
+                               BindTypeParameters(declaringType, parameterTypes),
+                               BindTypeParameters(declaringType, parameterOptionalCustomModifiers),
+                               BindTypeParameters(declaringType, parameterRequiredCustomModifiers));
+               }
+
+               internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
+               {
+                       byte flags = PROPERTY;
+                       if ((callingConvention & CallingConventions.HasThis) != 0)
+                       {
+                               flags |= HASTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+                       {
+                               flags |= EXPLICITTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.VarArgs) != 0)
+                       {
+                               flags |= VARARG;
+                       }
+                       bb.Write(flags);
+                       bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
+                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
+                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
+                       WriteType(module, bb, propertyType);
+                       if (parameterTypes != null)
+                       {
+                               for (int i = 0; i < parameterTypes.Length; i++)
+                               {
+                                       if (parameterRequiredCustomModifiers != null)
+                                       {
+                                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterRequiredCustomModifiers[i]);
+                                       }
+                                       if (parameterOptionalCustomModifiers != null)
+                                       {
+                                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterOptionalCustomModifiers[i]);
+                                       }
+                                       WriteType(module, bb, parameterTypes[i]);
+                               }
+                       }
+               }
+
+               internal Type GetParameter(int parameter)
+               {
+                       return parameterTypes[parameter];
+               }
+
+               internal Type[] GetOptionalCustomModifiers(int parameter)
+               {
+                       return parameterOptionalCustomModifiers == null ? Type.EmptyTypes : parameterOptionalCustomModifiers[parameter];
+               }
+
+               internal Type[] GetRequiredCustomModifiers(int parameter)
+               {
+                       return parameterRequiredCustomModifiers == null ? Type.EmptyTypes : parameterRequiredCustomModifiers[parameter];
+               }
+
+               internal static PropertySignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       byte flags = br.ReadByte();
+                       if ((flags & PROPERTY) == 0)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       CallingConventions callingConvention = CallingConventions.Standard;
+                       if ((flags & HASTHIS) != 0)
+                       {
+                               callingConvention |= CallingConventions.HasThis;
+                       }
+                       if ((flags & EXPLICITTHIS) != 0)
+                       {
+                               callingConvention |= CallingConventions.ExplicitThis;
+                       }
+                       Type returnType;
+                       Type[] returnTypeRequiredCustomModifiers;
+                       Type[] returnTypeOptionalCustomModifiers;
+                       Type[] parameterTypes;
+                       Type[][] parameterRequiredCustomModifiers;
+                       Type[][] parameterOptionalCustomModifiers;
+                       int paramCount = br.ReadCompressedInt();
+                       ReadCustomModifiers(module, br, context, out returnTypeRequiredCustomModifiers, out returnTypeOptionalCustomModifiers);
+                       returnType = ReadRetType(module, br, context);
+                       parameterTypes = new Type[paramCount];
+                       parameterRequiredCustomModifiers = null;
+                       parameterOptionalCustomModifiers = null;
+                       for (int i = 0; i < parameterTypes.Length; i++)
+                       {
+                               if (IsCustomModifier(br.PeekByte()))
+                               {
+                                       if (parameterOptionalCustomModifiers == null)
+                                       {
+                                               parameterOptionalCustomModifiers = new Type[parameterTypes.Length][];
+                                               parameterRequiredCustomModifiers = new Type[parameterTypes.Length][];
+                                       }
+                                       ReadCustomModifiers(module, br, context, out parameterRequiredCustomModifiers[i], out parameterOptionalCustomModifiers[i]);
+                               }
+                               parameterTypes[i] = ReadParam(module, br, context);
+                       }
+                       return new PropertySignature(callingConvention, returnType, returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
+                               parameterTypes, parameterOptionalCustomModifiers, parameterRequiredCustomModifiers);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/AssemblyReader.cs b/mcs/class/IKVM.Reflection/Reader/AssemblyReader.cs
new file mode 100644 (file)
index 0000000..08d66dd
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Configuration.Assemblies;
+using System.IO;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class AssemblyReader : Assembly
+       {
+               private const int ContainsNoMetaData = 0x0001;
+               private readonly string location;
+               private readonly ModuleReader manifestModule;
+               private readonly Module[] externalModules;
+
+               internal AssemblyReader(string location, ModuleReader manifestModule)
+                       : base(manifestModule.universe)
+               {
+                       this.location = location;
+                       this.manifestModule = manifestModule;
+                       externalModules = new Module[manifestModule.File.records.Length];
+               }
+
+               public override string Location
+               {
+                       get { return location; }
+               }
+
+               public override string FullName
+               {
+                       get { return GetName().FullName; }
+               }
+
+               public override AssemblyName GetName()
+               {
+                       return GetNameImpl(ref manifestModule.AssemblyTable.records[0]);
+               }
+
+               private AssemblyName GetNameImpl(ref AssemblyTable.Record rec)
+               {
+                       AssemblyName name = new AssemblyName();
+                       name.Name = manifestModule.GetString(rec.Name);
+                       name.Version = new Version(rec.MajorVersion, rec.MinorVersion, rec.BuildNumber, rec.RevisionNumber);
+                       if (rec.PublicKey != 0)
+                       {
+                               name.SetPublicKey(manifestModule.GetBlobCopy(rec.PublicKey));
+                       }
+                       else
+                       {
+                               name.SetPublicKey(Empty<byte>.Array);
+                       }
+                       if (rec.Culture != 0)
+                       {
+                               name.CultureInfo = new System.Globalization.CultureInfo(manifestModule.GetString(rec.Culture));
+                       }
+                       else
+                       {
+                               name.CultureInfo = System.Globalization.CultureInfo.InvariantCulture;
+                       }
+                       name.HashAlgorithm = (AssemblyHashAlgorithm)rec.HashAlgId;
+                       name.CodeBase = this.CodeBase;
+                       name.Flags = (AssemblyNameFlags)rec.Flags;
+                       return name;
+               }
+
+               public override Type[] GetTypes()
+               {
+                       if (externalModules.Length == 0)
+                       {
+                               return manifestModule.GetTypes();
+                       }
+
+                       List<Type> list = new List<Type>();
+                       foreach (Module module in GetModules(false))
+                       {
+                               list.AddRange(module.GetTypes());
+                       }
+                       return list.ToArray();
+               }
+
+               internal override Type GetTypeImpl(string typeName)
+               {
+                       Type type = manifestModule.GetType(typeName);
+                       for (int i = 0; type == null && i < externalModules.Length; i++)
+                       {
+                               if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
+                               {
+                                       type = GetModule(i).GetType(typeName);
+                               }
+                       }
+                       return type;
+               }
+
+               public override string ImageRuntimeVersion
+               {
+                       get { return manifestModule.ImageRuntimeVersion; }
+               }
+
+               public override Module ManifestModule
+               {
+                       get { return manifestModule; }
+               }
+
+               public override Module[] GetLoadedModules(bool getResourceModules)
+               {
+                       List<Module> list = new List<Module>();
+                       list.Add(manifestModule);
+                       foreach (Module m in externalModules)
+                       {
+                               if (m != null)
+                               {
+                                       list.Add(m);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public override Module[] GetModules(bool getResourceModules)
+               {
+                       if (externalModules.Length == 0)
+                       {
+                               return new Module[] { manifestModule };
+                       }
+                       else
+                       {
+                               List<Module> list = new List<Module>();
+                               list.Add(manifestModule);
+                               for (int i = 0; i < manifestModule.File.records.Length; i++)
+                               {
+                                       if (getResourceModules || (manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
+                                       {
+                                               list.Add(GetModule(i));
+                                       }
+                               }
+                               return list.ToArray();
+                       }
+               }
+
+               public override Module GetModule(string name)
+               {
+                       if (name.Equals(manifestModule.ScopeName, StringComparison.InvariantCultureIgnoreCase))
+                       {
+                               return manifestModule;
+                       }
+                       int index = GetModuleIndex(name);
+                       if (index != -1)
+                       {
+                               return GetModule(index);
+                       }
+                       return null;
+               }
+
+               private int GetModuleIndex(string name)
+               {
+                       for (int i = 0; i < manifestModule.File.records.Length; i++)
+                       {
+                               if (name.Equals(manifestModule.GetString(manifestModule.File.records[i].Name), StringComparison.InvariantCultureIgnoreCase))
+                               {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               }
+
+               private Module GetModule(int index)
+               {
+                       if (externalModules[index] != null)
+                       {
+                               return externalModules[index];
+                       }
+                       // TODO add ModuleResolve event
+                       string location = Path.Combine(Path.GetDirectoryName(this.location), manifestModule.GetString(manifestModule.File.records[index].Name));
+                       return LoadModule(index, File.ReadAllBytes(location), location);
+               }
+
+               private Module LoadModule(int index, byte[] rawModule, string location)
+               {
+                       if ((manifestModule.File.records[index].Flags & ContainsNoMetaData) != 0)
+                       {
+                               return externalModules[index] = new ResourceModule(this, manifestModule.GetString(manifestModule.File.records[index].Name), location);
+                       }
+                       else
+                       {
+                               return externalModules[index] = new ModuleReader(this, manifestModule.universe, new MemoryStream(rawModule), location);
+                       }
+               }
+
+               public override Module LoadModule(string moduleName, byte[] rawModule)
+               {
+                       int index = GetModuleIndex(moduleName);
+                       if (index == -1)
+                       {
+                               throw new ArgumentException();
+                       }
+                       if (externalModules[index] != null)
+                       {
+                               return externalModules[index];
+                       }
+                       return LoadModule(index, rawModule, null);
+               }
+
+               public override MethodInfo EntryPoint
+               {
+                       get { return manifestModule.GetEntryPoint(); }
+               }
+
+               public override string[] GetManifestResourceNames()
+               {
+                       return manifestModule.GetManifestResourceNames();
+               }
+
+               public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+               {
+                       return manifestModule.GetManifestResourceInfo(resourceName);
+               }
+
+               public override Stream GetManifestResourceStream(string resourceName)
+               {
+                       return manifestModule.GetManifestResourceStream(resourceName);
+               }
+
+               public override AssemblyName[] GetReferencedAssemblies()
+               {
+                       return manifestModule.__GetReferencedAssemblies();
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return manifestModule.GetCustomAttributes(0x20000001, attributeType);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/ByteReader.cs b/mcs/class/IKVM.Reflection/Reader/ByteReader.cs
new file mode 100644 (file)
index 0000000..edd1054
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class ByteReader
+       {
+               private byte[] buffer;
+               private int pos;
+               private int end;
+
+               internal ByteReader(byte[] buffer, int offset, int length)
+               {
+                       this.buffer = buffer;
+                       this.pos = offset;
+                       this.end = pos + length;
+               }
+
+               internal static ByteReader FromBlob(byte[] blobHeap, int blob)
+               {
+                       ByteReader br = new ByteReader(blobHeap, blob, 4);
+                       int length = br.ReadCompressedInt();
+                       br.end = br.pos + length;
+                       return br;
+               }
+
+               internal int Length
+               {
+                       get { return end - pos; }
+               }
+
+               internal byte PeekByte()
+               {
+                       if (pos == end)
+                               throw new BadImageFormatException();
+                       return buffer[pos];
+               }
+
+               internal byte ReadByte()
+               {
+                       if (pos == end)
+                               throw new BadImageFormatException();
+                       return buffer[pos++];
+               }
+
+               internal byte[] ReadBytes(int count)
+               {
+                       if (count < 0)
+                               throw new BadImageFormatException();
+                       if (end - pos < count)
+                               throw new BadImageFormatException();
+                       byte[] buf = new byte[count];
+                       Buffer.BlockCopy(buffer, pos, buf, 0, count);
+                       pos += count;
+                       return buf;
+               }
+
+               internal int ReadCompressedInt()
+               {
+                       byte b1 = ReadByte();
+                       if (b1 <= 0x7F)
+                       {
+                               return b1;
+                       }
+                       else if ((b1 & 0xC0) == 0x80)
+                       {
+                               byte b2 = ReadByte();
+                               return ((b1 & 0x3F) << 8) | b2;
+                       }
+                       else
+                       {
+                               byte b2 = ReadByte();
+                               byte b3 = ReadByte();
+                               byte b4 = ReadByte();
+                               return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
+                       }
+               }
+
+               internal string ReadString()
+               {
+                       if (PeekByte() == 0xFF)
+                       {
+                               pos++;
+                               return null;
+                       }
+                       int length = ReadCompressedInt();
+                       string str = Encoding.UTF8.GetString(buffer, pos, length);
+                       pos += length;
+                       return str;
+               }
+
+               internal char ReadChar()
+               {
+                       return (char)ReadInt16();
+               }
+
+               internal sbyte ReadSByte()
+               {
+                       return (sbyte)ReadByte();
+               }
+
+               internal short ReadInt16()
+               {
+                       if (end - pos < 2)
+                               throw new BadImageFormatException();
+                       byte b1 = buffer[pos++];
+                       byte b2 = buffer[pos++];
+                       return (short)(b1 | (b2 << 8));
+               }
+
+               internal ushort ReadUInt16()
+               {
+                       return (ushort)ReadInt16();
+               }
+
+               internal int ReadInt32()
+               {
+                       if (end - pos < 4)
+                               throw new BadImageFormatException();
+                       byte b1 = buffer[pos++];
+                       byte b2 = buffer[pos++];
+                       byte b3 = buffer[pos++];
+                       byte b4 = buffer[pos++];
+                       return (int)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24));
+               }
+
+               internal uint ReadUInt32()
+               {
+                       return (uint)ReadInt32();
+               }
+
+               internal long ReadInt64()
+               {
+                       ulong lo = ReadUInt32();
+                       ulong hi = ReadUInt32();
+                       return (long)(lo | (hi << 32));
+               }
+
+               internal ulong ReadUInt64()
+               {
+                       return (ulong)ReadInt64();
+               }
+
+               internal float ReadSingle()
+               {
+                       if (end - pos < 4)
+                               throw new BadImageFormatException();
+                       float value = BitConverter.ToSingle(buffer, pos);
+                       pos += 4;
+                       return value;
+               }
+
+               internal double ReadDouble()
+               {
+                       return BitConverter.Int64BitsToDouble(ReadInt64());
+               }
+
+               internal ByteReader Slice(int length)
+               {
+                       if (end - pos < length)
+                               throw new BadImageFormatException();
+                       ByteReader br = new ByteReader(buffer, pos, length);
+                       pos += length;
+                       return br;
+               }
+
+               // NOTE this method only works if the original offset was aligned and for alignments that are a power of 2
+               internal void Align(int alignment)
+               {
+                       alignment--;
+                       pos = (pos + alignment) & ~alignment;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/EventInfoImpl.cs b/mcs/class/IKVM.Reflection/Reader/EventInfoImpl.cs
new file mode 100644 (file)
index 0000000..82591b0
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class EventInfoImpl : EventInfo
+       {
+               private readonly ModuleReader module;
+               private readonly Type declaringType;
+               private readonly int index;
+               private bool isPublic;
+               private bool isStatic;
+               private bool flagsCached;
+
+               internal EventInfoImpl(ModuleReader module, Type declaringType, int index)
+               {
+                       this.module = module;
+                       this.declaringType = declaringType;
+                       this.index = index;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       EventInfoImpl other = obj as EventInfoImpl;
+                       return other != null && other.declaringType == declaringType && other.index == index;
+               }
+
+               public override int GetHashCode()
+               {
+                       return declaringType.GetHashCode() * 123 + index;
+               }
+
+               public override EventAttributes Attributes
+               {
+                       get { return (EventAttributes)module.Event.records[index].EventFlags; }
+               }
+
+               public override MethodInfo GetAddMethod(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.AddOn);
+               }
+
+               public override MethodInfo GetRaiseMethod(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Fire);
+               }
+
+               public override MethodInfo GetRemoveMethod(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.RemoveOn);
+               }
+
+               public override MethodInfo[] GetOtherMethods(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethods(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Other);
+               }
+
+               public override Type EventHandlerType
+               {
+                       get { return module.ResolveType(module.Event.records[index].EventType, declaringType); }
+               }
+
+               public override string Name
+               {
+                       get { return module.GetString(module.Event.records[index].Name); }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType; }
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return (EventTable.Index << 24) + index + 1; }
+               }
+
+               internal override bool IsPublic
+               {
+                       get
+                       {
+                               if (!flagsCached)
+                               {
+                                       ComputeFlags();
+                               }
+                               return isPublic;
+                       }
+               }
+
+               internal override bool IsStatic
+               {
+                       get
+                       {
+                               if (!flagsCached)
+                               {
+                                       ComputeFlags();
+                               }
+                               return isStatic;
+                       }
+               }
+
+               private void ComputeFlags()
+               {
+                       module.MethodSemantics.ComputeFlags(module, this.MetadataToken, out isPublic, out isStatic);
+                       flagsCached = true;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/Field.cs b/mcs/class/IKVM.Reflection/Reader/Field.cs
new file mode 100644 (file)
index 0000000..f9bcca6
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class FieldDefImpl : FieldInfo
+       {
+               private readonly ModuleReader module;
+               private readonly TypeDefImpl declaringType;
+               private readonly int index;
+               private FieldSignature lazyFieldSig;
+
+               internal FieldDefImpl(ModuleReader module, TypeDefImpl declaringType, int index)
+               {
+                       this.module = module;
+                       this.declaringType = declaringType;
+                       this.index = index;
+               }
+
+               public override FieldAttributes Attributes
+               {
+                       get { return (FieldAttributes)module.Field.records[index].Flags; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType.IsModulePseudoType ? null : declaringType; }
+               }
+
+               public override string Name
+               {
+                       get { return module.GetString(module.Field.records[index].Name); }
+               }
+
+               public override string ToString()
+               {
+                       return this.FieldType.Name + " " + this.Name;
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return (FieldTable.Index << 24) + index + 1; }
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       return module.Constant.GetRawConstantValue(module, this.MetadataToken);
+               }
+
+               public override void __GetDataFromRVA(byte[] data, int offset, int length)
+               {
+                       int rid = index + 1;
+                       // TODO binary search?
+                       for (int i = 0; i < module.FieldRVA.records.Length; i++)
+                       {
+                               if (module.FieldRVA.records[i].Field == rid)
+                               {
+                                       int rva = module.FieldRVA.records[i].RVA;
+                                       if (rva == 0)
+                                       {
+                                               // C++ assemblies can have fields that have an RVA that is zero
+                                               Array.Clear(data, offset, length);
+                                               return;
+                                       }
+                                       module.SeekRVA(rva);
+                                       while (length > 0)
+                                       {
+                                               int read = module.stream.Read(data, offset, length);
+                                               if (read == 0)
+                                               {
+                                                       // C++ assemblies can have fields that have an RVA that lies outside of the file
+                                                       break;
+                                               }
+                                               offset += read;
+                                               length -= read;
+                                       }
+                                       return;
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       List<CustomAttributeData> list = module.GetCustomAttributes(this.MetadataToken, attributeType);
+                       if ((this.Attributes & FieldAttributes.HasFieldMarshal) != 0
+                               && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_MarshalAsAttribute)))
+                       {
+                               list.Add(MarshalSpec.GetMarshalAsAttribute(module, this.MetadataToken));
+                       }
+                       if (declaringType.IsExplicitLayout
+                               && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_FieldOffsetAttribute)))
+                       {
+                               int rid = index + 1;
+                               // TODO use binary search?
+                               for (int i = 0; i < module.FieldLayout.records.Length; i++)
+                               {
+                                       if (module.FieldLayout.records[i].Field == rid)
+                                       {
+                                               ConstructorInfo constructor = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute.GetConstructor(new Type[] { module.universe.System_Int32 });
+                                               list.Add(new CustomAttributeData(constructor,
+                                                       new object[] { module.FieldLayout.records[i].Offset },
+                                                       null));
+                                               break;
+                                       }
+                               }
+                       }
+                       return list;
+               }
+
+               internal override FieldSignature FieldSignature
+               {
+                       get { return lazyFieldSig ?? (lazyFieldSig = FieldSignature.ReadSig(module, module.GetBlob(module.Field.records[index].Signature), declaringType)); }
+               }
+
+               internal override int ImportTo(Emit.ModuleBuilder module)
+               {
+                       return module.ImportMethodOrField(declaringType, this.Name, this.FieldSignature);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/GenericTypeParameter.cs b/mcs/class/IKVM.Reflection/Reader/GenericTypeParameter.cs
new file mode 100644 (file)
index 0000000..2f961f9
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       abstract class TypeParameterType : Type
+       {
+               public sealed override string AssemblyQualifiedName
+               {
+                       get { return null; }
+               }
+
+               public sealed override bool IsValueType
+               {
+                       get { return (this.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; }
+               }
+
+               public sealed override Type BaseType
+               {
+                       get
+                       {
+                               foreach (Type type in GetGenericParameterConstraints())
+                               {
+                                       if (!type.IsInterface && !type.IsGenericParameter)
+                                       {
+                                               return type;
+                                       }
+                               }
+                               return this.IsValueType ? this.Module.universe.System_ValueType : this.Module.universe.System_Object;
+                       }
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       List<Type> list = new List<Type>();
+                       foreach (Type type in GetGenericParameterConstraints())
+                       {
+                               if (type.IsInterface)
+                               {
+                                       list.Add(type);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public sealed override TypeAttributes Attributes
+               {
+                       get { return TypeAttributes.Public; }
+               }
+
+               public sealed override Type UnderlyingSystemType
+               {
+                       get { return this; }
+               }
+
+               public sealed override string FullName
+               {
+                       get { return null; }
+               }
+
+               public sealed override string ToString()
+               {
+                       return this.Name;
+               }
+
+               public sealed override bool IsGenericParameter
+               {
+                       get { return true; }
+               }
+       }
+
+       sealed class UnboundGenericMethodParameter : TypeParameterType
+       {
+               private static readonly DummyModule module = new DummyModule();
+               private readonly int position;
+
+               private sealed class DummyModule : Module
+               {
+                       internal DummyModule()
+                               : base(new Universe())
+                       {
+                       }
+
+                       public override bool Equals(object obj)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override int GetHashCode()
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override string ToString()
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override int MDStreamVersion
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       public override Assembly Assembly
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       internal override Type GetTypeImpl(string typeName)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       internal override void GetTypesImpl(List<Type> list)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override string FullyQualifiedName
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       public override string Name
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       public override Guid ModuleVersionId
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override string ResolveString(int metadataToken)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       public override string ScopeName
+                       {
+                               get { throw new InvalidOperationException(); }
+                       }
+
+                       public override AssemblyName[] __GetReferencedAssemblies()
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       internal override Type GetModuleType()
+                       {
+                               throw new InvalidOperationException();
+                       }
+
+                       internal override ByteReader GetBlob(int blobIndex)
+                       {
+                               throw new InvalidOperationException();
+                       }
+               }
+
+               internal static Type Make(int position)
+               {
+                       return module.CanonicalizeType(new UnboundGenericMethodParameter(position));
+               }
+
+               private UnboundGenericMethodParameter(int position)
+               {
+                       this.position = position;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       UnboundGenericMethodParameter other = obj as UnboundGenericMethodParameter;
+                       return other != null && other.position == position;
+               }
+
+               public override int GetHashCode()
+               {
+                       return position;
+               }
+
+               public override string Namespace
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override string Name
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override int MetadataToken
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               public override int GenericParameterPosition
+               {
+                       get { return position; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return null; }
+               }
+
+               public override MethodBase DeclaringMethod
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override Type[] GetGenericParameterConstraints()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public override GenericParameterAttributes GenericParameterAttributes
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               internal override Type BindTypeParameters(IGenericBinder binder)
+               {
+                       return binder.BindMethodParameter(this);
+               }
+       }
+
+       sealed class GenericTypeParameter : TypeParameterType
+       {
+               private readonly ModuleReader module;
+               private readonly int index;
+
+               internal GenericTypeParameter(ModuleReader module, int index)
+               {
+                       this.module = module;
+                       this.index = index;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return base.Equals(obj);
+               }
+
+               public override int GetHashCode()
+               {
+                       return base.GetHashCode();
+               }
+
+               public override string Namespace
+               {
+                       get { return DeclaringType.Namespace; }
+               }
+
+               public override string Name
+               {
+                       get { return module.GetString(module.GenericParam.records[index].Name); }
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return (GenericParamTable.Index << 24) + index + 1; }
+               }
+
+               public override int GenericParameterPosition
+               {
+                       get { return module.GenericParam.records[index].Number; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get
+                       {
+                               int owner = module.GenericParam.records[index].Owner;
+                               return (owner >> 24) == TypeDefTable.Index ? module.ResolveType(owner) : null;
+                       }
+               }
+
+               public override MethodBase DeclaringMethod
+               {
+                       get
+                       {
+                               int owner = module.GenericParam.records[index].Owner;
+                               return (owner >> 24) == MethodDefTable.Index ? module.ResolveMethod(owner) : null;
+                       }
+               }
+
+               public override Type[] GetGenericParameterConstraints()
+               {
+                       IGenericContext context = (this.DeclaringMethod as IGenericContext) ?? this.DeclaringType;
+                       List<Type> list = new List<Type>();
+                       int token = this.MetadataToken;
+                       // TODO use binary search
+                       for (int i = 0; i < module.GenericParamConstraint.records.Length; i++)
+                       {
+                               if (module.GenericParamConstraint.records[i].Owner == token)
+                               {
+                                       list.Add(module.ResolveType(module.GenericParamConstraint.records[i].Constraint, context));
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public override GenericParameterAttributes GenericParameterAttributes
+               {
+                       get { return (GenericParameterAttributes)module.GenericParam.records[index].Flags; }
+               }
+
+               internal override Type BindTypeParameters(IGenericBinder binder)
+               {
+                       int owner = module.GenericParam.records[index].Owner;
+                       if ((owner >> 24) == MethodDefTable.Index)
+                       {
+                               return binder.BindMethodParameter(this);
+                       }
+                       else
+                       {
+                               return binder.BindTypeParameter(this);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/MetadataReader.cs b/mcs/class/IKVM.Reflection/Reader/MetadataReader.cs
new file mode 100644 (file)
index 0000000..0bbe475
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class MetadataReader : MetadataRW
+       {
+               private readonly BinaryReader br;
+
+               internal MetadataReader(ModuleReader module, BinaryReader br, byte heapSizes)
+                       : base(module, (heapSizes & 0x01) != 0, (heapSizes & 0x02) != 0, (heapSizes & 0x04) != 0)
+               {
+                       this.br = br;
+               }
+
+               internal short ReadInt16()
+               {
+                       return br.ReadInt16();
+               }
+
+               internal ushort ReadUInt16()
+               {
+                       return br.ReadUInt16();
+               }
+
+               internal int ReadInt32()
+               {
+                       return br.ReadInt32();
+               }
+
+               internal int ReadStringIndex()
+               {
+                       if (bigStrings)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadGuidIndex()
+               {
+                       if (bigGuids)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadBlobIndex()
+               {
+                       if (bigBlobs)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadResolutionScope()
+               {
+                       int codedIndex;
+                       if (bigResolutionScope)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 3)
+                       {
+                               case 0:
+                                       return (ModuleTable.Index << 24) + (codedIndex >> 2);
+                               case 1:
+                                       return (ModuleRefTable.Index << 24) + (codedIndex >> 2);
+                               case 2:
+                                       return (AssemblyRefTable.Index << 24) + (codedIndex >> 2);
+                               case 3:
+                                       return (TypeRefTable.Index << 24) + (codedIndex >> 2);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadTypeDefOrRef()
+               {
+                       int codedIndex;
+                       if (bigTypeDefOrRef)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 3)
+                       {
+                               case 0:
+                                       return (TypeDefTable.Index << 24) + (codedIndex >> 2);
+                               case 1:
+                                       return (TypeRefTable.Index << 24) + (codedIndex >> 2);
+                               case 2:
+                                       return (TypeSpecTable.Index << 24) + (codedIndex >> 2);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadMemberRefParent()
+               {
+                       int codedIndex;
+                       if (bigMemberRefParent)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 7)
+                       {
+                               case 0:
+                                       return (TypeDefTable.Index << 24) + (codedIndex >> 3);
+                               case 1:
+                                       return (TypeRefTable.Index << 24) + (codedIndex >> 3);
+                               case 2:
+                                       return (ModuleRefTable.Index << 24) + (codedIndex >> 3);
+                               case 3:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 3);
+                               case 4:
+                                       return (TypeSpecTable.Index << 24) + (codedIndex >> 3);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadHasCustomAttribute()
+               {
+                       int codedIndex;
+                       if (bigHasCustomAttribute)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 31)
+                       {
+                               case 0:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 5);
+                               case 1:
+                                       return (FieldTable.Index << 24) + (codedIndex >> 5);
+                               case 2:
+                                       return (TypeRefTable.Index << 24) + (codedIndex >> 5);
+                               case 3:
+                                       return (TypeDefTable.Index << 24) + (codedIndex >> 5);
+                               case 4:
+                                       return (ParamTable.Index << 24) + (codedIndex >> 5);
+                               case 5:
+                                       return (InterfaceImplTable.Index << 24) + (codedIndex >> 5);
+                               case 6:
+                                       return (MemberRefTable.Index << 24) + (codedIndex >> 5);
+                               case 7:
+                                       return (ModuleTable.Index << 24) + (codedIndex >> 5);
+                               case 8:
+                                       throw new BadImageFormatException();
+                               case 9:
+                                       return (PropertyTable.Index << 24) + (codedIndex >> 5);
+                               case 10:
+                                       return (EventTable.Index << 24) + (codedIndex >> 5);
+                               case 11:
+                                       return (StandAloneSigTable.Index << 24) + (codedIndex >> 5);
+                               case 12:
+                                       return (ModuleRefTable.Index << 24) + (codedIndex >> 5);
+                               case 13:
+                                       return (TypeSpecTable.Index << 24) + (codedIndex >> 5);
+                               case 14:
+                                       return (AssemblyTable.Index << 24) + (codedIndex >> 5);
+                               case 15:
+                                       return (AssemblyRefTable.Index << 24) + (codedIndex >> 5);
+                               case 16:
+                                       return (FileTable.Index << 24) + (codedIndex >> 5);
+                               case 17:
+                                       return (ExportedTypeTable.Index << 24) + (codedIndex >> 5);
+                               case 18:
+                                       return (ManifestResourceTable.Index << 24) + (codedIndex >> 5);
+                               case 19:
+                                       return (GenericParamTable.Index << 24) + (codedIndex >> 5);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadCustomAttributeType()
+               {
+                       int codedIndex;
+                       if (bigCustomAttributeType)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 7)
+                       {
+                               case 2:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 3);
+                               case 3:
+                                       return (MemberRefTable.Index << 24) + (codedIndex >> 3);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadMethodDefOrRef()
+               {
+                       int codedIndex;
+                       if (bigMethodDefOrRef)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 1)
+                       {
+                               case 0:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 1);
+                               case 1:
+                                       return (MemberRefTable.Index << 24) + (codedIndex >> 1);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadHasConstant()
+               {
+                       int codedIndex;
+                       if (bigHasConstant)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 3)
+                       {
+                               case 0:
+                                       return (FieldTable.Index << 24) + (codedIndex >> 2);
+                               case 1:
+                                       return (ParamTable.Index << 24) + (codedIndex >> 2);
+                               case 2:
+                                       return (PropertyTable.Index << 24) + (codedIndex >> 2);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadHasSemantics()
+               {
+                       int codedIndex;
+                       if (bigHasSemantics)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 1)
+                       {
+                               case 0:
+                                       return (EventTable.Index << 24) + (codedIndex >> 1);
+                               case 1:
+                                       return (PropertyTable.Index << 24) + (codedIndex >> 1);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadHasFieldMarshal()
+               {
+                       int codedIndex;
+                       if (bigHasFieldMarshal)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 1)
+                       {
+                               case 0:
+                                       return (FieldTable.Index << 24) + (codedIndex >> 1);
+                               case 1:
+                                       return (ParamTable.Index << 24) + (codedIndex >> 1);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadHasDeclSecurity()
+               {
+                       int codedIndex;
+                       if (bigHasDeclSecurity)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 3)
+                       {
+                               case 0:
+                                       return (TypeDefTable.Index << 24) + (codedIndex >> 2);
+                               case 1:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 2);
+                               case 2:
+                                       return (AssemblyTable.Index << 24) + (codedIndex >> 2);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadTypeOrMethodDef()
+               {
+                       int codedIndex;
+                       if (bigTypeOrMethodDef)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 1)
+                       {
+                               case 0:
+                                       return (TypeDefTable.Index << 24) + (codedIndex >> 1);
+                               case 1:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 1);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadMemberForwarded()
+               {
+                       int codedIndex;
+                       if (bigMemberForwarded)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 1)
+                       {
+                               case 0:
+                                       return (FieldTable.Index << 24) + (codedIndex >> 1);
+                               case 1:
+                                       return (MethodDefTable.Index << 24) + (codedIndex >> 1);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal int ReadImplementation()
+               {
+                       int codedIndex;
+                       if (bigImplementation)
+                       {
+                               codedIndex = br.ReadInt32();
+                       }
+                       else
+                       {
+                               codedIndex = br.ReadUInt16();
+                       }
+                       switch (codedIndex & 3)
+                       {
+                               case 0:
+                                       return (FileTable.Index << 24) + (codedIndex >> 2);
+                               case 1:
+                                       return (AssemblyRefTable.Index << 24) + (codedIndex >> 2);
+                               case 2:
+                                       return (ExportedTypeTable.Index << 24) + (codedIndex >> 2);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               private int ReadToken(int table, bool big)
+               {
+                       int rid;
+                       if (big)
+                       {
+                               rid = br.ReadInt32();
+                       }
+                       else
+                       {
+                               rid = br.ReadUInt16();
+                       }
+                       return rid | (table << 24);
+               }
+
+               internal int ReadField()
+               {
+                       if (bigField)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadMethodDef()
+               {
+                       if (bigMethodDef)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadParam()
+               {
+                       if (bigParam)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadProperty()
+               {
+                       if (bigProperty)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadEvent()
+               {
+                       if (bigEvent)
+                       {
+                               return br.ReadInt32();
+                       }
+                       else
+                       {
+                               return br.ReadUInt16();
+                       }
+               }
+
+               internal int ReadTypeDef()
+               {
+                       return ReadToken(TypeDefTable.Index, bigTypeDef);
+               }
+
+               internal int ReadGenericParam()
+               {
+                       return ReadToken(GenericParamTable.Index, bigGenericParam);
+               }
+
+               internal int ReadModuleRef()
+               {
+                       return ReadToken(ModuleRefTable.Index, bigModuleRef);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/Method.cs b/mcs/class/IKVM.Reflection/Reader/Method.cs
new file mode 100644 (file)
index 0000000..c3d77f5
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class MethodDefImpl : MethodInfo
+       {
+               private readonly ModuleReader module;
+               private readonly int index;
+               private readonly TypeDefImpl declaringType;
+               private MethodSignature lazyMethodSignature;
+               private ParameterInfo returnParameter;
+               private ParameterInfo[] parameters;
+               private Type[] typeArgs;
+
+               internal MethodDefImpl(ModuleReader module, TypeDefImpl declaringType, int index)
+               {
+                       this.module = module;
+                       this.index = index;
+                       this.declaringType = declaringType;
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       return GetMethodBody(this);
+               }
+
+               internal MethodBody GetMethodBody(IGenericContext context)
+               {
+                       if ((GetMethodImplementationFlags() & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL)
+                       {
+                               // method is not IL
+                               return null;
+                       }
+                       int rva = module.MethodDef.records[index].RVA;
+                       return rva == 0 ? null : new MethodBody(module, rva, context);
+               }
+
+               public override CallingConventions CallingConvention
+               {
+                       get { return this.MethodSignature.CallingConvention; }
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { return (MethodAttributes)module.MethodDef.records[index].Flags; }
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       return (MethodImplAttributes)module.MethodDef.records[index].ImplFlags;
+               }
+
+               public override ParameterInfo[] GetParameters()
+               {
+                       PopulateParameters();
+                       return (ParameterInfo[])parameters.Clone();
+               }
+
+               private void PopulateParameters()
+               {
+                       if (parameters == null)
+                       {
+                               MethodSignature methodSignature = this.MethodSignature;
+                               parameters = new ParameterInfo[methodSignature.GetParameterCount()];
+                               int parameter = module.MethodDef.records[index].ParamList - 1;
+                               int end = module.MethodDef.records.Length > index + 1 ? module.MethodDef.records[index + 1].ParamList - 1 : module.Param.records.Length;
+                               for (; parameter < end; parameter++)
+                               {
+                                       int seq = module.Param.records[parameter].Sequence - 1;
+                                       if (seq == -1)
+                                       {
+                                               returnParameter = new ParameterInfoImpl(this, seq, parameter);
+                                       }
+                                       else
+                                       {
+                                               parameters[seq] = new ParameterInfoImpl(this, seq, parameter);
+                                       }
+                               }
+                               for (int i = 0; i < parameters.Length; i++)
+                               {
+                                       if (parameters[i] == null)
+                                       {
+                                               parameters[i] = new ParameterInfoImpl(this, i, -1);
+                                       }
+                               }
+                               if (returnParameter == null)
+                               {
+                                       returnParameter = new ParameterInfoImpl(this, -1, -1);
+                               }
+                       }
+               }
+
+               internal override int ParameterCount
+               {
+                       get { return this.MethodSignature.GetParameterCount(); }
+               }
+
+               public override ParameterInfo ReturnParameter
+               {
+                       get
+                       {
+                               PopulateParameters();
+                               return returnParameter;
+                       }
+               }
+
+               public override Type ReturnType
+               {
+                       get
+                       {
+                               return this.ReturnParameter.ParameterType;
+                       }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType.IsModulePseudoType ? null : declaringType; }
+               }
+
+               public override string Name
+               {
+                       get { return module.GetString(module.MethodDef.records[index].Name); }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return (MethodDefTable.Index << 24) + index + 1; }
+               }
+
+               public override bool IsGenericMethodDefinition
+               {
+                       get
+                       {
+                               PopulateGenericArguments();
+                               return typeArgs.Length > 0;
+                       }
+               }
+
+               public override bool IsGenericMethod
+               {
+                       get { return IsGenericMethodDefinition; }
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       PopulateGenericArguments();
+                       return Util.Copy(typeArgs);
+               }
+
+               private void PopulateGenericArguments()
+               {
+                       if (typeArgs == null)
+                       {
+                               int token = this.MetadataToken;
+                               int first = module.GenericParam.FindFirstByOwner(token);
+                               if (first == -1)
+                               {
+                                       typeArgs = Type.EmptyTypes;
+                               }
+                               else
+                               {
+                                       List<Type> list = new List<Type>();
+                                       int len = module.GenericParam.records.Length;
+                                       for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
+                                       {
+                                               list.Add(new GenericTypeParameter(module, i));
+                                       }
+                                       typeArgs = list.ToArray();
+                               }
+                       }
+               }
+
+               internal override Type GetGenericMethodArgument(int index)
+               {
+                       PopulateGenericArguments();
+                       return typeArgs[index];
+               }
+
+               internal override int GetGenericMethodArgumentCount()
+               {
+                       PopulateGenericArguments();
+                       return typeArgs.Length;
+               }
+
+               public override MethodInfo GetGenericMethodDefinition()
+               {
+                       if (this.IsGenericMethodDefinition)
+                       {
+                               return this;
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+               {
+                       return new GenericMethodInstance(declaringType, this, typeArguments);
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       List<CustomAttributeData> list = module.GetCustomAttributes(this.MetadataToken, attributeType);
+                       if ((this.Attributes & MethodAttributes.PinvokeImpl) != 0
+                               && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_DllImportAttribute)))
+                       {
+                               CreateDllImportPseudoCustomAttribute(list);
+                       }
+                       return list;
+               }
+
+               private void CreateDllImportPseudoCustomAttribute(List<CustomAttributeData> attribs)
+               {
+                       int token = this.MetadataToken;
+                       // TODO use binary search?
+                       for (int i = 0; i < module.ImplMap.records.Length; i++)
+                       {
+                               if (module.ImplMap.records[i].MemberForwarded == token)
+                               {
+                                       const short NoMangle = 0x0001;
+                                       const short CharSetMask = 0x0006;
+                                       const short CharSetNotSpec = 0x0000;
+                                       const short CharSetAnsi = 0x0002;
+                                       const short CharSetUnicode = 0x0004;
+                                       const short CharSetAuto = 0x0006;
+                                       const short SupportsLastError = 0x0040;
+                                       const short CallConvMask = 0x0700;
+                                       const short CallConvWinapi = 0x0100;
+                                       const short CallConvCdecl = 0x0200;
+                                       const short CallConvStdcall = 0x0300;
+                                       const short CallConvThiscall = 0x0400;
+                                       const short CallConvFastcall = 0x0500;
+                                       // non-standard flags
+                                       const short BestFitOn = 0x0010;
+                                       const short BestFitOff = 0x0020;
+                                       const short CharMapErrorOn = 0x1000;
+                                       const short CharMapErrorOff = 0x2000;
+
+                                       Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute;
+                                       ConstructorInfo constructor = type.GetConstructor(new Type[] { module.universe.System_String });
+                                       List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>();
+                                       int flags = module.ImplMap.records[i].MappingFlags;
+                                       string entryPoint = module.GetString(module.ImplMap.records[i].ImportName);
+                                       string dllName = module.GetString(module.ModuleRef.records[(module.ImplMap.records[i].ImportScope & 0xFFFFFF) - 1]);
+                                       System.Runtime.InteropServices.CharSet? charSet;
+                                       switch (flags & CharSetMask)
+                                       {
+                                               case CharSetAnsi:
+                                                       charSet = System.Runtime.InteropServices.CharSet.Ansi;
+                                                       break;
+                                               case CharSetUnicode:
+                                                       charSet = System.Runtime.InteropServices.CharSet.Unicode;
+                                                       break;
+                                               case CharSetAuto:
+                                                       charSet = System.Runtime.InteropServices.CharSet.Auto;
+                                                       break;
+                                               case CharSetNotSpec:
+                                               default:
+                                                       charSet = null;
+                                                       break;
+                                       }
+                                       System.Runtime.InteropServices.CallingConvention callingConvention;
+                                       switch (flags & CallConvMask)
+                                       {
+                                               case CallConvCdecl:
+                                                       callingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
+                                                       break;
+                                               case CallConvFastcall:
+                                                       callingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
+                                                       break;
+                                               case CallConvStdcall:
+                                                       callingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
+                                                       break;
+                                               case CallConvThiscall:
+                                                       callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
+                                                       break;
+                                               case CallConvWinapi:
+                                               default:
+                                                       callingConvention = System.Runtime.InteropServices.CallingConvention.Winapi;
+                                                       break;
+                                       }
+                                       list.Add(MakeNamedArgument(type, "EntryPoint", entryPoint));
+                                       list.Add(MakeNamedArgument(type, "ExactSpelling", flags, NoMangle));
+                                       list.Add(MakeNamedArgument(type, "SetLastError", flags, SupportsLastError));
+                                       list.Add(MakeNamedArgument(type, "PreserveSig", (int)GetMethodImplementationFlags(), (int)MethodImplAttributes.PreserveSig));
+                                       list.Add(MakeNamedArgument(type, "CallingConvention", (int)callingConvention));
+                                       if (charSet.HasValue)
+                                       {
+                                               list.Add(MakeNamedArgument(type, "CharSet", (int)charSet.Value));
+                                       }
+                                       if ((flags & (BestFitOn | BestFitOff)) != 0)
+                                       {
+                                               list.Add(MakeNamedArgument(type, "BestFitMapping", flags, BestFitOn));
+                                       }
+                                       if ((flags & (CharMapErrorOn | CharMapErrorOff)) != 0)
+                                       {
+                                               list.Add(MakeNamedArgument(type, "ThrowOnUnmappableChar", flags, CharMapErrorOn));
+                                       }
+                                       attribs.Add(new CustomAttributeData(constructor, new object[] { dllName }, list));
+                                       return;
+                               }
+                       }
+               }
+
+               private static CustomAttributeNamedArgument MakeNamedArgument(Type type, string field, string value)
+               {
+                       return new CustomAttributeNamedArgument(type.GetField(field), new CustomAttributeTypedArgument(type.Module.universe.System_String, value));
+               }
+
+               private static CustomAttributeNamedArgument MakeNamedArgument(Type type, string field, int value)
+               {
+                       return new CustomAttributeNamedArgument(type.GetField(field), new CustomAttributeTypedArgument(type.Module.universe.System_Int32, value));
+               }
+
+               private static CustomAttributeNamedArgument MakeNamedArgument(Type type, string field, int flags, int flagMask)
+               {
+                       return new CustomAttributeNamedArgument(type.GetField(field), new CustomAttributeTypedArgument(type.Module.universe.System_Boolean, (flags & flagMask) != 0));
+               }
+
+               internal override MethodSignature MethodSignature
+               {
+                       get { return lazyMethodSignature ?? (lazyMethodSignature = MethodSignature.ReadSig(module, module.GetBlob(module.MethodDef.records[index].Signature), this)); }
+               }
+
+               internal override int ImportTo(Emit.ModuleBuilder module)
+               {
+                       return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature);
+               }
+       }
+
+       sealed class ParameterInfoImpl : ParameterInfo
+       {
+               private readonly MethodDefImpl method;
+               private readonly int position;
+               private readonly int index;
+
+               internal ParameterInfoImpl(MethodDefImpl method, int position, int index)
+               {
+                       this.method = method;
+                       this.position = position;
+                       this.index = index;
+               }
+
+               public override string Name
+               {
+                       get { return index == -1 ? null : ((ModuleReader)this.Module).GetString(this.Module.Param.records[index].Name); }
+               }
+
+               public override Type ParameterType
+               {
+                       get { return position == -1 ? method.MethodSignature.GetReturnType(method) : method.MethodSignature.GetParameterType(method, position); }
+               }
+
+               public override ParameterAttributes Attributes
+               {
+                       get { return index == -1 ? ParameterAttributes.None : (ParameterAttributes)this.Module.Param.records[index].Flags; }
+               }
+
+               public override int Position
+               {
+                       get { return position; }
+               }
+
+               public override object RawDefaultValue
+               {
+                       get
+                       {
+                               if ((this.Attributes & ParameterAttributes.HasDefault) != 0)
+                               {
+                                       return this.Module.Constant.GetRawConstantValue(this.Module, this.MetadataToken);
+                               }
+                               Universe universe = this.Module.universe;
+                               if (this.ParameterType == universe.System_Decimal)
+                               {
+                                       Type attr = universe.System_Runtime_CompilerServices_DecimalConstantAttribute;
+                                       if (attr != null)
+                                       {
+                                               foreach (CustomAttributeData cad in GetCustomAttributesData(attr))
+                                               {
+                                                       IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
+                                                       if (args.Count == 5)
+                                                       {
+                                                               if (args[0].ArgumentType == universe.System_Byte
+                                                                       && args[1].ArgumentType == universe.System_Byte
+                                                                       && args[2].ArgumentType == universe.System_Int32
+                                                                       && args[3].ArgumentType == universe.System_Int32
+                                                                       && args[4].ArgumentType == universe.System_Int32)
+                                                               {
+                                                                       return new Decimal((int)args[4].Value, (int)args[3].Value, (int)args[2].Value, (byte)args[1].Value != 0, (byte)args[0].Value);
+                                                               }
+                                                               else if (args[0].ArgumentType == universe.System_Byte
+                                                                       && args[1].ArgumentType == universe.System_Byte
+                                                                       && args[2].ArgumentType == universe.System_UInt32
+                                                                       && args[3].ArgumentType == universe.System_UInt32
+                                                                       && args[4].ArgumentType == universe.System_UInt32)
+                                                               {
+                                                                       return new Decimal(unchecked((int)(uint)args[4].Value), unchecked((int)(uint)args[3].Value), unchecked((int)(uint)args[2].Value), (byte)args[1].Value != 0, (byte)args[0].Value);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               if ((this.Attributes & ParameterAttributes.Optional) != 0)
+                               {
+                                       return Missing.Value;
+                               }
+                               return null;
+                       }
+               }
+
+               public override Type[] GetRequiredCustomModifiers()
+               {
+                       return Util.Copy(position == -1 ? method.MethodSignature.GetReturnTypeRequiredCustomModifiers(method) : method.MethodSignature.GetParameterRequiredCustomModifiers(method, position));
+               }
+
+               public override Type[] GetOptionalCustomModifiers()
+               {
+                       return Util.Copy(position == -1 ? method.MethodSignature.GetReturnTypeOptionalCustomModifiers(method) : method.MethodSignature.GetParameterOptionalCustomModifiers(method, position));
+               }
+
+               public override MemberInfo Member
+               {
+                       get
+                       {
+                               // return the right ConstructorInfo wrapper
+                               return method.Module.ResolveMethod(method.MetadataToken);
+                       }
+               }
+
+               public override int MetadataToken
+               {
+                       get
+                       {
+                               // for parameters that don't have a row in the Param table, we return 0x08000000 (because index is -1 in that case),
+                               // just like .NET
+                               return (ParamTable.Index << 24) + index + 1;
+                       }
+               }
+
+               internal override Module Module
+               {
+                       get { return method.Module; }
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       IList<CustomAttributeData> list = base.GetCustomAttributesData(attributeType);
+                       if ((this.Attributes & ParameterAttributes.HasFieldMarshal) != 0
+                               && (attributeType == null || attributeType.IsAssignableFrom(this.Module.universe.System_Runtime_InteropServices_MarshalAsAttribute)))
+                       {
+                               list.Add(MarshalSpec.GetMarshalAsAttribute(this.Module, this.MetadataToken));
+                       }
+                       return list;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/ModuleReader.cs b/mcs/class/IKVM.Reflection/Reader/ModuleReader.cs
new file mode 100644 (file)
index 0000000..3f04d71
--- /dev/null
@@ -0,0 +1,1028 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class StreamHeader
+       {
+               internal uint Offset;
+               internal uint Size;
+               internal string Name;
+
+               internal void Read(BinaryReader br)
+               {
+                       Offset = br.ReadUInt32();
+                       Size = br.ReadUInt32();
+                       byte[] buf = new byte[32];
+                       byte b;
+                       int len = 0;
+                       while ((b = br.ReadByte()) != 0)
+                       {
+                               buf[len++] = b;
+                       }
+                       Name = Encoding.UTF8.GetString(buf, 0, len); ;
+                       int padding = -1 + ((len + 4) & ~3) - len;
+                       br.BaseStream.Seek(padding, SeekOrigin.Current);
+               }
+       }
+
+       sealed class ModuleReader : Module
+       {
+               internal readonly Stream stream;
+               private readonly string location;
+               private Assembly assembly;
+               private readonly PEReader peFile = new PEReader();
+               private readonly CliHeader cliHeader = new CliHeader();
+               private string imageRuntimeVersion;
+               private int metadataStreamVersion;
+               private byte[] stringHeap;
+               private byte[] blobHeap;
+               private byte[] userStringHeap;
+               private byte[] guidHeap;
+               private TypeDefImpl[] typeDefs;
+               private TypeDefImpl moduleType;
+               private Assembly[] assemblyRefs;
+               private Type[] typeRefs;
+               private Type[] typeSpecs;
+               private FieldInfo[] fields;
+               private MethodBase[] methods;
+               private MemberInfo[] memberRefs;
+               private Dictionary<int, string> strings = new Dictionary<int, string>();
+               private Dictionary<string, Type> types = new Dictionary<string, Type>();
+               private Dictionary<string, LazyForwardedType> forwardedTypes = new Dictionary<string, LazyForwardedType>();
+
+               private sealed class LazyForwardedType
+               {
+                       private readonly int assemblyRef;
+                       private Type type;
+
+                       internal LazyForwardedType(int assemblyRef)
+                       {
+                               this.assemblyRef = assemblyRef;
+                       }
+
+                       internal Type GetType(ModuleReader module, string typeName)
+                       {
+                               if (type == null)
+                               {
+                                       Assembly asm = module.ResolveAssemblyRef(assemblyRef);
+                                       type = asm.GetType(typeName, true);
+                               }
+                               return type;
+                       }
+               }
+
+               internal ModuleReader(AssemblyReader assembly, Universe universe, Stream stream, string location)
+                       : base(universe)
+               {
+                       this.stream = stream;
+                       this.location = location;
+                       Read();
+                       if (assembly == null && AssemblyTable.records.Length != 0)
+                       {
+                               assembly = new AssemblyReader(location, this);
+                       }
+                       this.assembly = assembly;
+               }
+
+               private void Read()
+               {
+                       BinaryReader br = new BinaryReader(stream);
+                       peFile.Read(br);
+                       stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin);
+                       cliHeader.Read(br);
+                       stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaDataRVA), SeekOrigin.Begin);
+                       foreach (StreamHeader sh in ReadStreamHeaders(br, out imageRuntimeVersion))
+                       {
+                               switch (sh.Name)
+                               {
+                                       case "#Strings":
+                                               stringHeap = ReadHeap(stream, sh);
+                                               break;
+                                       case "#Blob":
+                                               blobHeap = ReadHeap(stream, sh);
+                                               break;
+                                       case "#US":
+                                               userStringHeap = ReadHeap(stream, sh);
+                                               break;
+                                       case "#GUID":
+                                               guidHeap = ReadHeap(stream, sh);
+                                               break;
+                                       case "#~":
+                                               stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaDataRVA + sh.Offset), SeekOrigin.Begin);
+                                               ReadTables(br);
+                                               break;
+                                       default:
+                                               throw new BadImageFormatException("Unsupported stream: " + sh.Name);
+                               }
+                       }
+               }
+
+               internal void SetAssembly(Assembly assembly)
+               {
+                       this.assembly = assembly;
+               }
+
+               private static StreamHeader[] ReadStreamHeaders(BinaryReader br, out string Version)
+               {
+                       uint Signature = br.ReadUInt32();
+                       if (Signature != 0x424A5342)
+                       {
+                               throw new BadImageFormatException("Invalid metadata signature");
+                       }
+                       ushort MajorVersion = br.ReadUInt16();
+                       ushort MinorVersion = br.ReadUInt16();
+                       uint Reserved = br.ReadUInt32();
+                       uint Length = br.ReadUInt32();
+                       byte[] buf = br.ReadBytes((int)Length);
+                       Version = Encoding.UTF8.GetString(buf).TrimEnd('\u0000');
+                       ushort Flags = br.ReadUInt16();
+                       ushort Streams = br.ReadUInt16();
+                       StreamHeader[] streamHeaders = new StreamHeader[Streams];
+                       for (int i = 0; i < streamHeaders.Length; i++)
+                       {
+                               streamHeaders[i] = new StreamHeader();
+                               streamHeaders[i].Read(br);
+                       }
+                       return streamHeaders;
+               }
+
+               private void ReadTables(BinaryReader br)
+               {
+                       Table[] tables = GetTables();
+                       uint Reserved0 = br.ReadUInt32();
+                       byte MajorVersion = br.ReadByte();
+                       byte MinorVersion = br.ReadByte();
+                       metadataStreamVersion = MajorVersion << 16 | MinorVersion;
+                       byte HeapSizes = br.ReadByte();
+                       byte Reserved7 = br.ReadByte();
+                       ulong Valid = br.ReadUInt64();
+                       ulong Sorted = br.ReadUInt64();
+                       for (int i = 0; i < 64; i++)
+                       {
+                               if ((Valid & (1UL << i)) != 0)
+                               {
+                                       tables[i].RowCount = br.ReadInt32();
+                               }
+                               else if (tables[i] != null)
+                               {
+                                       tables[i].RowCount = 0;
+                               }
+                       }
+                       MetadataReader mr = new MetadataReader(this, br, HeapSizes);
+                       for (int i = 0; i < 64; i++)
+                       {
+                               if ((Valid & (1UL << i)) != 0)
+                               {
+                                       tables[i].Read(mr);
+                               }
+                       }
+               }
+
+               private byte[] ReadHeap(Stream stream, StreamHeader sh)
+               {
+                       byte[] buf = new byte[sh.Size];
+                       stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaDataRVA + sh.Offset), SeekOrigin.Begin);
+                       for (int pos = 0; pos < buf.Length; )
+                       {
+                               int read = stream.Read(buf, pos, buf.Length - pos);
+                               if (read == 0)
+                               {
+                                       throw new BadImageFormatException();
+                               }
+                               pos += read;
+                       }
+                       return buf;
+               }
+
+               internal void SeekRVA(int rva)
+               {
+                       stream.Seek(peFile.RvaToFileOffset((uint)rva), SeekOrigin.Begin);
+               }
+
+               internal override void GetTypesImpl(List<Type> list)
+               {
+                       PopulateTypeDef();
+                       foreach (TypeDefImpl type in typeDefs)
+                       {
+                               if (type != moduleType)
+                               {
+                                       list.Add(type);
+                               }
+                       }
+               }
+
+               private void PopulateTypeDef()
+               {
+                       if (typeDefs == null)
+                       {
+                               typeDefs = new TypeDefImpl[TypeDef.records.Length];
+                               for (int i = 0; i < typeDefs.Length; i++)
+                               {
+                                       TypeDefImpl type = new TypeDefImpl(this, i);
+                                       typeDefs[i] = type;
+                                       if (type.IsModulePseudoType)
+                                       {
+                                               moduleType = type;
+                                       }
+                                       else
+                                       {
+                                               types.Add(type.FullName, type);
+                                       }
+                               }
+                               // add forwarded types to forwardedTypes dictionary (because Module.GetType(string) should return them)
+                               for (int i = 0; i < ExportedType.records.Length; i++)
+                               {
+                                       int implementation = ExportedType.records[i].Implementation;
+                                       if (implementation >> 24 == AssemblyRefTable.Index)
+                                       {
+                                               string typeName = GetTypeName(ExportedType.records[i].TypeNamespace, ExportedType.records[i].TypeName);
+                                               forwardedTypes.Add(typeName, new LazyForwardedType((implementation & 0xFFFFFF) - 1));
+                                       }
+                               }
+                       }
+               }
+
+               internal string GetString(int index)
+               {
+                       if (index == 0)
+                       {
+                               return null;
+                       }
+                       string str;
+                       if (!strings.TryGetValue(index, out str))
+                       {
+                               int len = 0;
+                               while (stringHeap[index + len] != 0)
+                               {
+                                       len++;
+                               }
+                               str = Encoding.UTF8.GetString(stringHeap, index, len);
+                               strings.Add(index, str);
+                       }
+                       return str;
+               }
+
+               private static int ReadCompressedInt(byte[] buffer, ref int offset)
+               {
+                       byte b1 = buffer[offset++];
+                       if (b1 <= 0x7F)
+                       {
+                               return b1;
+                       }
+                       else if ((b1 & 0xC0) == 0x80)
+                       {
+                               byte b2 = buffer[offset++];
+                               return ((b1 & 0x3F) << 8) | b2;
+                       }
+                       else
+                       {
+                               byte b2 = buffer[offset++];
+                               byte b3 = buffer[offset++];
+                               byte b4 = buffer[offset++];
+                               return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
+                       }
+               }
+
+               internal byte[] GetBlobCopy(int blobIndex)
+               {
+                       int len = ReadCompressedInt(blobHeap, ref blobIndex);
+                       byte[] buf = new byte[len];
+                       Buffer.BlockCopy(blobHeap, blobIndex, buf, 0, len);
+                       return buf;
+               }
+
+               internal override ByteReader GetBlob(int blobIndex)
+               {
+                       return ByteReader.FromBlob(blobHeap, blobIndex);
+               }
+
+               public override string ResolveString(int metadataToken)
+               {
+                       string str;
+                       if (!strings.TryGetValue(metadataToken, out str))
+                       {
+                               if ((metadataToken >> 24) != 0x70)
+                               {
+                                       throw new ArgumentOutOfRangeException();
+                               }
+                               int index = metadataToken & 0xFFFFFF;
+                               int len = ReadCompressedInt(userStringHeap, ref index) & ~1;
+                               str = Encoding.Unicode.GetString(userStringHeap, index, len);
+                               strings.Add(metadataToken, str);
+                       }
+                       return str;
+               }
+
+               internal Type ResolveType(int metadataToken, IGenericContext context)
+               {
+                       switch (metadataToken >> 24)
+                       {
+                               case TypeDefTable.Index:
+                                       PopulateTypeDef();
+                                       return typeDefs[(metadataToken & 0xFFFFFF) - 1];
+                               case TypeRefTable.Index:
+                                       {
+                                               if (typeRefs == null)
+                                               {
+                                                       typeRefs = new Type[TypeRef.records.Length];
+                                               }
+                                               int index = (metadataToken & 0xFFFFFF) - 1;
+                                               if (typeRefs[index] == null)
+                                               {
+                                                       int scope = TypeRef.records[index].ResolutionScope;
+                                                       switch (scope >> 24)
+                                                       {
+                                                               case AssemblyRefTable.Index:
+                                                                       {
+                                                                               Assembly assembly = ResolveAssemblyRef((scope & 0xFFFFFF) - 1);
+                                                                               string typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
+                                                                               Type type = assembly.GetType(typeName);
+                                                                               if (type == null)
+                                                                               {
+                                                                                       throw new TypeLoadException(String.Format("Type '{0}' not found in assembly '{1}'", typeName, assembly.FullName));
+                                                                               }
+                                                                               typeRefs[index] = type;
+                                                                               break;
+                                                                       }
+                                                               case TypeRefTable.Index:
+                                                                       {
+                                                                               Type outer = ResolveType(scope, null);
+                                                                               typeRefs[index] = outer.GetNestedType(GetString(TypeRef.records[index].TypeName), BindingFlags.Public | BindingFlags.NonPublic);
+                                                                               break;
+                                                                       }
+                                                               case ModuleTable.Index:
+                                                                       if (scope != 0 && scope != 1)
+                                                                       {
+                                                                               throw new NotImplementedException("self reference scope?");
+                                                                       }
+                                                                       typeRefs[index] = GetType(GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName));
+                                                                       break;
+                                                               case ModuleRefTable.Index:
+                                                                       {
+                                                                               Module module = ResolveModuleRef(ModuleRef.records[(scope & 0xFFFFFF) - 1]);
+                                                                               string typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
+                                                                               Type type = assembly.GetType(typeName);
+                                                                               if (type == null)
+                                                                               {
+                                                                                       throw new TypeLoadException(String.Format("Type '{0}' not found in module '{1}'", typeName, module.Name));
+                                                                               }
+                                                                               typeRefs[index] = type;
+                                                                               break;
+                                                                       }
+                                                               default:
+                                                                       throw new NotImplementedException("ResolutionScope = " + scope.ToString("X"));
+                                                       }
+                                               }
+                                               return typeRefs[index];
+                                       }
+                               case TypeSpecTable.Index:
+                                       {
+                                               if (typeSpecs == null)
+                                               {
+                                                       typeSpecs = new Type[TypeSpec.records.Length];
+                                               }
+                                               int index = (metadataToken & 0xFFFFFF) - 1;
+                                               Type type = typeSpecs[index];
+                                               if (type == null)
+                                               {
+                                                       TrackingGenericContext tc = context == null ? null : new TrackingGenericContext(context);
+                                                       type = Signature.ReadTypeSpec(this, ByteReader.FromBlob(blobHeap, TypeSpec.records[index]), tc);
+                                                       if (tc == null || !tc.IsUsed)
+                                                       {
+                                                               typeSpecs[index] = type;
+                                                       }
+                                               }
+                                               return type;
+                                       }
+                               default:
+                                       throw new NotImplementedException(String.Format("0x{0:X}", metadataToken));
+                       }
+               }
+
+               private Module ResolveModuleRef(int moduleNameIndex)
+               {
+                       string moduleName = GetString(moduleNameIndex);
+                       Module module = assembly.GetModule(moduleName);
+                       if (module == null)
+                       {
+                               throw new FileNotFoundException(moduleName);
+                       }
+                       return module;
+               }
+
+               private sealed class TrackingGenericContext : IGenericContext
+               {
+                       private readonly IGenericContext context;
+                       private bool used;
+
+                       internal TrackingGenericContext(IGenericContext context)
+                       {
+                               this.context = context;
+                       }
+
+                       internal bool IsUsed
+                       {
+                               get { return used; }
+                       }
+
+                       public Type GetGenericTypeArgument(int index)
+                       {
+                               used = true;
+                               return context.GetGenericTypeArgument(index);
+                       }
+
+                       public Type GetGenericMethodArgument(int index)
+                       {
+                               used = true;
+                               return context.GetGenericMethodArgument(index);
+                       }
+               }
+
+               public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       if ((metadataToken >> 24) == TypeSpecTable.Index)
+                       {
+                               return ResolveType(metadataToken, new GenericContext(genericTypeArguments, genericMethodArguments));
+                       }
+                       else
+                       {
+                               return ResolveType(metadataToken, null);
+                       }
+               }
+
+               private string GetTypeName(int typeNamespace, int typeName)
+               {
+                       if (typeNamespace == 0)
+                       {
+                               return GetString(typeName);
+                       }
+                       else
+                       {
+                               return GetString(typeNamespace) + "." + GetString(typeName);
+                       }
+               }
+
+               private Assembly ResolveAssemblyRef(int index)
+               {
+                       if (assemblyRefs == null)
+                       {
+                               assemblyRefs = new Assembly[AssemblyRef.RowCount];
+                       }
+                       if (assemblyRefs[index] == null)
+                       {
+                               assemblyRefs[index] = ResolveAssemblyRefImpl(ref AssemblyRef.records[index]);
+                       }
+                       return assemblyRefs[index];
+               }
+
+               private Assembly ResolveAssemblyRefImpl(ref AssemblyRefTable.Record rec)
+               {
+                       const int PublicKey = 0x0001;
+                       string name = String.Format("{0}, Version={1}.{2}.{3}.{4}, Culture={5}, {6}={7}",
+                               GetString(rec.Name),
+                               rec.MajorVersion,
+                               rec.MinorVersion,
+                               rec.BuildNumber,
+                               rec.RevisionNumber,
+                               rec.Culture == 0 ? "neutral" : GetString(rec.Culture),
+                               (rec.Flags & PublicKey) == 0 ? "PublicKeyToken" : "PublicKey",
+                               PublicKeyOrTokenToString(rec.PublicKeyOrToken));
+                       return universe.Load(name, this.Assembly, true);
+               }
+
+               private string PublicKeyOrTokenToString(int publicKeyOrToken)
+               {
+                       if (publicKeyOrToken == 0)
+                       {
+                               return "null";
+                       }
+                       ByteReader br = GetBlob(publicKeyOrToken);
+                       if (br.Length == 0)
+                       {
+                               return "null";
+                       }
+                       StringBuilder sb = new StringBuilder(br.Length * 2);
+                       while (br.Length > 0)
+                       {
+                               sb.AppendFormat("{0:x2}", br.ReadByte());
+                       }
+                       return sb.ToString();
+               }
+
+               public override Guid ModuleVersionId
+               {
+                       get
+                       {
+                               byte[] buf = new byte[16];
+                               Buffer.BlockCopy(guidHeap, 16 * (ModuleTable.records[0].Mvid - 1), buf, 0, 16);
+                               return new Guid(buf);
+                       }
+               }
+
+               public override string FullyQualifiedName
+               {
+                       get { return location ?? "<Unknown>"; }
+               }
+
+               public override string Name
+               {
+                       get { return location == null ? "<Unknown>" : System.IO.Path.GetFileName(location); }
+               }
+
+               public override Assembly Assembly
+               {
+                       get { return assembly; }
+               }
+
+               internal override Type GetTypeImpl(string typeName)
+               {
+                       PopulateTypeDef();
+                       Type type;
+                       if (!types.TryGetValue(typeName, out type))
+                       {
+                               LazyForwardedType fw;
+                               if (forwardedTypes.TryGetValue(typeName, out fw))
+                               {
+                                       return fw.GetType(this, typeName);
+                               }
+                       }
+                       return type;
+               }
+
+               public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       switch (metadataToken >> 24)
+                       {
+                               case FieldTable.Index:
+                                       return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
+                               case MemberRefTable.Index:
+                                       return GetMemberRef((metadataToken & 0xFFFFFF) - 1, genericTypeArguments, genericMethodArguments);
+                               case MethodDefTable.Index:
+                               case MethodSpecTable.Index:
+                                       return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
+                       }
+                       throw new ArgumentOutOfRangeException();
+               }
+
+               internal FieldInfo GetFieldAt(TypeDefImpl owner, int index)
+               {
+                       if (fields == null)
+                       {
+                               fields = new FieldInfo[Field.records.Length];
+                       }
+                       if (fields[index] == null)
+                       {
+                               fields[index] = new FieldDefImpl(this, owner ?? FindFieldOwner(index), index);
+                       }
+                       return fields[index];
+               }
+
+               public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       if ((metadataToken >> 24) == FieldTable.Index)
+                       {
+                               int index = (metadataToken & 0xFFFFFF) - 1;
+                               return GetFieldAt(null, index);
+                       }
+                       else if ((metadataToken >> 24) == MemberRefTable.Index)
+                       {
+                               FieldInfo field = GetMemberRef((metadataToken & 0xFFFFFF) - 1, genericTypeArguments, genericMethodArguments) as FieldInfo;
+                               if (field != null)
+                               {
+                                       return field;
+                               }
+                       }
+                       throw new ArgumentOutOfRangeException();
+               }
+
+               private TypeDefImpl FindFieldOwner(int fieldIndex)
+               {
+                       // TODO use binary search?
+                       for (int i = 0; i < TypeDef.records.Length; i++)
+                       {
+                               int field = TypeDef.records[i].FieldList - 1;
+                               int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].FieldList - 1 : Field.records.Length;
+                               if (field <= fieldIndex && fieldIndex < end)
+                               {
+                                       PopulateTypeDef();
+                                       return typeDefs[i];
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               internal MethodBase GetMethodAt(TypeDefImpl owner, int index)
+               {
+                       if (methods == null)
+                       {
+                               methods = new MethodBase[MethodDef.records.Length];
+                       }
+                       if (methods[index] == null)
+                       {
+                               MethodDefImpl method = new MethodDefImpl(this, owner ?? FindMethodOwner(index), index);
+                               methods[index] = method.IsConstructor ? new ConstructorInfoImpl(method) : (MethodBase)method;
+                       }
+                       return methods[index];
+               }
+
+               private sealed class GenericContext : IGenericContext
+               {
+                       private readonly Type[] genericTypeArguments;
+                       private readonly Type[] genericMethodArguments;
+
+                       internal GenericContext(Type[] genericTypeArguments, Type[] genericMethodArguments)
+                       {
+                               this.genericTypeArguments = genericTypeArguments;
+                               this.genericMethodArguments = genericMethodArguments;
+                       }
+
+                       public Type GetGenericTypeArgument(int index)
+                       {
+                               return genericTypeArguments[index];
+                       }
+
+                       public Type GetGenericMethodArgument(int index)
+                       {
+                               return genericMethodArguments[index];
+                       }
+               }
+
+               public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       if ((metadataToken >> 24) == MethodDefTable.Index)
+                       {
+                               int index = (metadataToken & 0xFFFFFF) - 1;
+                               return GetMethodAt(null, index);
+                       }
+                       else if ((metadataToken >> 24) == MemberRefTable.Index)
+                       {
+                               int index = (metadataToken & 0xFFFFFF) - 1;
+                               MethodBase method = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as MethodBase;
+                               if (method != null)
+                               {
+                                       return method;
+                               }
+                       }
+                       else if ((metadataToken >> 24) == MethodSpecTable.Index)
+                       {
+                               int index = (metadataToken & 0xFFFFFF) - 1;
+                               MethodInfo method = (MethodInfo)ResolveMethod(MethodSpec.records[index].Method, genericTypeArguments, genericMethodArguments);
+                               ByteReader instantiation = ByteReader.FromBlob(blobHeap, MethodSpec.records[index].Instantiation);
+                               return method.MakeGenericMethod(Signature.ReadMethodSpec(this, instantiation, new GenericContext(genericTypeArguments, genericMethodArguments)));
+                       }
+                       throw new ArgumentOutOfRangeException();
+               }
+
+               public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+               {
+                       if ((metadataToken >> 24) == MemberRefTable.Index)
+                       {
+                               int index = (metadataToken & 0xFFFFFF) - 1;
+                               int sig = MemberRef.records[index].Signature;
+                               return Signature.ReadOptionalParameterTypes(this, GetBlob(sig));
+                       }
+                       else if ((metadataToken >> 24) == MethodDefTable.Index)
+                       {
+                               // for convenience, we support passing a MethodDef token as well, because in some places
+                               // it makes sense to have a vararg method that is referred to by its methoddef (e.g. ldftn).
+                               // Note that MethodSpec doesn't make sense, because generic methods cannot be vararg.
+                               return Type.EmptyTypes;
+                       }
+                       throw new ArgumentOutOfRangeException();
+               }
+
+               public override string ScopeName
+               {
+                       get { return GetString(ModuleTable.records[0].Name); }
+               }
+
+               private TypeDefImpl FindMethodOwner(int methodIndex)
+               {
+                       // TODO use binary search?
+                       for (int i = 0; i < TypeDef.records.Length; i++)
+                       {
+                               int method = TypeDef.records[i].MethodList - 1;
+                               int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].MethodList - 1 : MethodDef.records.Length;
+                               if (method <= methodIndex && methodIndex < end)
+                               {
+                                       PopulateTypeDef();
+                                       return typeDefs[i];
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               private MemberInfo GetMemberRef(int index, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       if (memberRefs == null)
+                       {
+                               memberRefs = new MemberInfo[MemberRef.records.Length];
+                       }
+                       if (memberRefs[index] == null)
+                       {
+                               int owner = MemberRef.records[index].Class;
+                               int sig = MemberRef.records[index].Signature;
+                               string name = GetString(MemberRef.records[index].Name);
+                               switch (owner >> 24)
+                               {
+                                       case MethodDefTable.Index:
+                                               return GetMethodAt(null, (owner & 0xFFFFFF) - 1);
+                                       case ModuleRefTable.Index:
+                                               memberRefs[index] = ResolveTypeMemberRef(ResolveModuleType(owner), name, ByteReader.FromBlob(blobHeap, sig), genericTypeArguments, genericMethodArguments);
+                                               break;
+                                       case TypeDefTable.Index:
+                                       case TypeRefTable.Index:
+                                               memberRefs[index] = ResolveTypeMemberRef(ResolveType(owner), name, ByteReader.FromBlob(blobHeap, sig), genericTypeArguments, genericMethodArguments);
+                                               break;
+                                       case TypeSpecTable.Index:
+                                               return ResolveTypeMemberRef(ResolveType(owner, genericTypeArguments, genericMethodArguments), name, ByteReader.FromBlob(blobHeap, sig), genericTypeArguments, genericMethodArguments);
+                                       default:
+                                               throw new BadImageFormatException();
+                               }
+                       }
+                       return memberRefs[index];
+               }
+
+               private Type ResolveModuleType(int token)
+               {
+                       int index = (token & 0xFFFFFF) - 1;
+                       string name = GetString(ModuleRef.records[index]);
+                       Module module = assembly.GetModule(name);
+                       if (module == null || module.IsResource())
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       return module.GetModuleType();
+               }
+
+               private MemberInfo ResolveTypeMemberRef(Type type, string name, ByteReader sig, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       IGenericContext context;
+                       if ((genericTypeArguments == null && genericMethodArguments == null) || type.IsGenericType)
+                       {
+                               context = type;
+                       }
+                       else
+                       {
+                               context = new GenericContext(genericTypeArguments, genericMethodArguments);
+                       }
+                       if (sig.PeekByte() == Signature.FIELD)
+                       {
+                               Type org = type;
+                               FieldSignature fieldSig = FieldSignature.ReadSig(this, sig, context);
+                               do
+                               {
+                                       FieldInfo field = type.FindField(name, fieldSig);
+                                       if (field != null)
+                                       {
+                                               return field;
+                                       }
+                                       type = type.BaseType;
+                               } while (type != null);
+                               throw new MissingFieldException(org.ToString(), name);
+                       }
+                       else
+                       {
+                               Type org = type;
+                               MethodSignature methodSig = MethodSignature.ReadSig(this, sig, context);
+                               do
+                               {
+                                       MethodBase method = type.FindMethod(name, methodSig);
+                                       if (method != null)
+                                       {
+                                               return method;
+                                       }
+                                       type = type.BaseType;
+                               } while (type != null);
+                               throw new MissingMethodException(org.ToString(), name);
+                       }
+               }
+
+               internal new ByteReader ResolveSignature(int metadataToken)
+               {
+                       if ((metadataToken >> 24) == StandAloneSigTable.Index)
+                       {
+                               int index = (metadataToken & 0xFFFFFF) - 1;
+                               return ByteReader.FromBlob(blobHeap, StandAloneSig.records[index]);
+                       }
+                       throw new ArgumentOutOfRangeException();
+               }
+
+               public override __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       return MethodSignature.ReadStandAloneMethodSig(this, ResolveSignature(metadataToken), new GenericContext(genericTypeArguments, genericMethodArguments));
+               }
+
+               internal MethodInfo GetEntryPoint()
+               {
+                       if (cliHeader.EntryPointToken != 0 && (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0)
+                       {
+                               return (MethodInfo)ResolveMethod((int)cliHeader.EntryPointToken);
+                       }
+                       return null;
+               }
+
+               internal string[] GetManifestResourceNames()
+               {
+                       string[] names = new string[ManifestResource.records.Length];
+                       for (int i = 0; i < ManifestResource.records.Length; i++)
+                       {
+                               names[i] = GetString(ManifestResource.records[i].Name);
+                       }
+                       return names;
+               }
+
+               internal ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+               {
+                       for (int i = 0; i < ManifestResource.records.Length; i++)
+                       {
+                               if (resourceName == GetString(ManifestResource.records[i].Name))
+                               {
+                                       return new ManifestResourceInfo(this, i);
+                               }
+                       }
+                       return null;
+               }
+
+               internal Stream GetManifestResourceStream(string resourceName)
+               {
+                       for (int i = 0; i < ManifestResource.records.Length; i++)
+                       {
+                               if (resourceName == GetString(ManifestResource.records[i].Name))
+                               {
+                                       if (ManifestResource.records[i].Implementation != 0x26000000)
+                                       {
+                                               throw new NotImplementedException();
+                                       }
+                                       SeekRVA((int)cliHeader.ResourcesRVA + ManifestResource.records[i].Offset);
+                                       BinaryReader br = new BinaryReader(stream);
+                                       int length = br.ReadInt32();
+                                       return new MemoryStream(br.ReadBytes(length));
+                               }
+                       }
+                       throw new FileNotFoundException();
+               }
+
+               public override AssemblyName[] __GetReferencedAssemblies()
+               {
+                       List<AssemblyName> list = new List<AssemblyName>();
+                       for (int i = 0; i < AssemblyRef.records.Length; i++)
+                       {
+                               AssemblyName name = new AssemblyName();
+                               name.Name = GetString(AssemblyRef.records[i].Name);
+                               name.Version = new Version(
+                                       AssemblyRef.records[i].MajorVersion,
+                                       AssemblyRef.records[i].MinorVersion,
+                                       AssemblyRef.records[i].BuildNumber,
+                                       AssemblyRef.records[i].RevisionNumber);
+                               if (AssemblyRef.records[i].PublicKeyOrToken != 0)
+                               {
+                                       byte[] keyOrToken = GetBlobCopy(AssemblyRef.records[i].PublicKeyOrToken);
+                                       const int PublicKey = 0x0001;
+                                       if ((AssemblyRef.records[i].Flags & PublicKey) != 0)
+                                       {
+                                               name.SetPublicKey(keyOrToken);
+                                       }
+                                       else
+                                       {
+                                               name.SetPublicKeyToken(keyOrToken);
+                                       }
+                               }
+                               if (AssemblyRef.records[i].Culture != 0)
+                               {
+                                       name.CultureInfo = new System.Globalization.CultureInfo(GetString(AssemblyRef.records[i].Culture));
+                               }
+                               else
+                               {
+                                       name.CultureInfo = System.Globalization.CultureInfo.InvariantCulture;
+                               }
+                               name.Flags = (AssemblyNameFlags)AssemblyRef.records[i].Flags;
+                               list.Add(name);
+                       }
+                       return list.ToArray();
+               }
+
+               internal override Type GetModuleType()
+               {
+                       PopulateTypeDef();
+                       return moduleType;
+               }
+
+               internal string ImageRuntimeVersion
+               {
+                       get { return imageRuntimeVersion; }
+               }
+
+               public override int MDStreamVersion
+               {
+                       get { return metadataStreamVersion; }
+               }
+
+               public override void __GetDataDirectoryEntry(int index, out int rva, out int length)
+               {
+                       peFile.GetDataDirectoryEntry(index, out rva, out length);
+               }
+
+               public override long __RelativeVirtualAddressToFileOffset(int rva)
+               {
+                       return peFile.RvaToFileOffset((uint)rva);
+               }
+
+               public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+               {
+                       peKind = 0;
+                       if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_ILONLY) != 0)
+                       {
+                               peKind |= PortableExecutableKinds.ILOnly;
+                       }
+                       if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_32BITREQUIRED) != 0)
+                       {
+                               peKind |= PortableExecutableKinds.Required32Bit;
+                       }
+                       if (peFile.OptionalHeader.Magic == IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+                       {
+                               peKind |= PortableExecutableKinds.PE32Plus;
+                       }
+
+                       machine = (ImageFileMachine)peFile.FileHeader.Machine;
+               }
+
+               public override int __Subsystem
+               {
+                       get { return peFile.OptionalHeader.Subsystem; }
+               }
+
+               public override IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
+               {
+                       string typeName;
+                       switch ((multiple ? 1 : 0) + (security ? 2 : 0))
+                       {
+                               case 0:
+                                       typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHere";
+                                       break;
+                               case 1:
+                                       typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHereM";
+                                       break;
+                               case 2:
+                                       typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHereS";
+                                       break;
+                               case 3:
+                               default:
+                                       typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHereSM";
+                                       break;
+                       }
+                       List<CustomAttributeData> list = new List<CustomAttributeData>();
+                       for (int i = 0; i < CustomAttribute.records.Length; i++)
+                       {
+                               if ((CustomAttribute.records[i].Parent >> 24) == TypeRefTable.Index)
+                               {
+                                       int index = (CustomAttribute.records[i].Parent & 0xFFFFFF) - 1;
+                                       if (typeName == GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName))
+                                       {
+                                               ConstructorInfo constructor = (ConstructorInfo)ResolveMethod(CustomAttribute.records[i].Type);
+                                               list.Add(new CustomAttributeData(this.Assembly, constructor, GetBlob(CustomAttribute.records[i].Value)));
+                                       }
+                               }
+                       }
+                       return list;
+               }
+
+               internal override void Dispose()
+               {
+                       stream.Close();
+               }
+
+               internal override void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
+               {
+                       PopulateTypeDef();
+                       manifestModule.ExportTypes(typeDefs, fileToken);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/PEReader.cs b/mcs/class/IKVM.Reflection/Reader/PEReader.cs
new file mode 100644 (file)
index 0000000..dcafcf0
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using BYTE = System.Byte;
+using WORD = System.UInt16;
+using DWORD = System.UInt32;
+using ULONGLONG = System.UInt64;
+using System.IO;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class MSDOS_HEADER
+       {
+               internal const WORD MAGIC_MZ = 0x5A4D;
+
+               internal WORD signature;        // 'MZ'
+               // skip 58 bytes
+               internal DWORD peSignatureOffset;
+       }
+
+       sealed class IMAGE_NT_HEADERS
+       {
+               public const DWORD MAGIC_SIGNATURE = 0x00004550;        // "PE\0\0"
+
+               public DWORD Signature;
+               public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
+               public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
+
+               internal void Read(BinaryReader br)
+               {
+                       Signature = br.ReadUInt32();
+                       if (Signature != IMAGE_NT_HEADERS.MAGIC_SIGNATURE)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       FileHeader.Read(br);
+                       OptionalHeader.Read(br);
+               }
+       }
+
+       sealed class IMAGE_FILE_HEADER
+       {
+               public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
+               public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
+               public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
+
+               public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
+               public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
+               public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
+               public const WORD IMAGE_FILE_DLL = 0x2000;
+
+               public WORD Machine;
+               public WORD NumberOfSections;
+               public DWORD TimeDateStamp;
+               public DWORD PointerToSymbolTable;
+               public DWORD NumberOfSymbols;
+               public WORD SizeOfOptionalHeader;
+               public WORD Characteristics;
+
+               internal void Read(BinaryReader br)
+               {
+                       Machine = br.ReadUInt16();
+                       NumberOfSections = br.ReadUInt16();
+                       TimeDateStamp = br.ReadUInt32();
+                       PointerToSymbolTable = br.ReadUInt32();
+                       NumberOfSymbols = br.ReadUInt32();
+                       SizeOfOptionalHeader = br.ReadUInt16();
+                       Characteristics = br.ReadUInt16();
+               }
+       }
+
+       sealed class IMAGE_OPTIONAL_HEADER
+       {
+               public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
+               public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
+
+               public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
+               public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
+
+               public const WORD IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040;
+               public const WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100;
+               public const WORD IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400;
+               public const WORD IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000;
+
+               public WORD Magic;
+               public BYTE MajorLinkerVersion;
+               public BYTE MinorLinkerVersion;
+               public DWORD SizeOfCode;
+               public DWORD SizeOfInitializedData;
+               public DWORD SizeOfUninitializedData;
+               public DWORD AddressOfEntryPoint;
+               public DWORD BaseOfCode;
+               public DWORD BaseOfData;
+               public ULONGLONG ImageBase;
+               public DWORD SectionAlignment;
+               public DWORD FileAlignment;
+               public WORD MajorOperatingSystemVersion;
+               public WORD MinorOperatingSystemVersion;
+               public WORD MajorImageVersion;
+               public WORD MinorImageVersion;
+               public WORD MajorSubsystemVersion;
+               public WORD MinorSubsystemVersion;
+               public DWORD Win32VersionValue;
+               public DWORD SizeOfImage;
+               public DWORD SizeOfHeaders;
+               public DWORD CheckSum;
+               public WORD Subsystem;
+               public WORD DllCharacteristics;
+               public ULONGLONG SizeOfStackReserve;
+               public ULONGLONG SizeOfStackCommit;
+               public ULONGLONG SizeOfHeapReserve;
+               public ULONGLONG SizeOfHeapCommit;
+               public DWORD LoaderFlags;
+               public DWORD NumberOfRvaAndSizes;
+               public IMAGE_DATA_DIRECTORY[] DataDirectory;
+
+               internal void Read(BinaryReader br)
+               {
+                       Magic = br.ReadUInt16();
+                       if (Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       MajorLinkerVersion = br.ReadByte();
+                       MinorLinkerVersion = br.ReadByte();
+                       SizeOfCode = br.ReadUInt32();
+                       SizeOfInitializedData = br.ReadUInt32();
+                       SizeOfUninitializedData = br.ReadUInt32();
+                       AddressOfEntryPoint = br.ReadUInt32();
+                       BaseOfCode = br.ReadUInt32();
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               BaseOfData = br.ReadUInt32();
+                               ImageBase = br.ReadUInt32();
+                       }
+                       else
+                       {
+                               ImageBase = br.ReadUInt64();
+                       }
+                       SectionAlignment = br.ReadUInt32();
+                       FileAlignment = br.ReadUInt32();
+                       MajorOperatingSystemVersion = br.ReadUInt16();
+                       MinorOperatingSystemVersion = br.ReadUInt16();
+                       MajorImageVersion = br.ReadUInt16();
+                       MinorImageVersion = br.ReadUInt16();
+                       MajorSubsystemVersion = br.ReadUInt16();
+                       MinorSubsystemVersion = br.ReadUInt16();
+                       Win32VersionValue = br.ReadUInt32();
+                       SizeOfImage = br.ReadUInt32();
+                       SizeOfHeaders = br.ReadUInt32();
+                       CheckSum = br.ReadUInt32();
+                       Subsystem = br.ReadUInt16();
+                       DllCharacteristics = br.ReadUInt16();
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               SizeOfStackReserve = br.ReadUInt32();
+                               SizeOfStackCommit = br.ReadUInt32();
+                               SizeOfHeapReserve = br.ReadUInt32();
+                               SizeOfHeapCommit = br.ReadUInt32();
+                       }
+                       else
+                       {
+                               SizeOfStackReserve = br.ReadUInt64();
+                               SizeOfStackCommit = br.ReadUInt64();
+                               SizeOfHeapReserve = br.ReadUInt64();
+                               SizeOfHeapCommit = br.ReadUInt64();
+                       }
+                       LoaderFlags = br.ReadUInt32();
+                       NumberOfRvaAndSizes = br.ReadUInt32();
+                       DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes];
+                       for (uint i = 0; i < NumberOfRvaAndSizes; i++)
+                       {
+                               DataDirectory[i] = new IMAGE_DATA_DIRECTORY();
+                               DataDirectory[i].Read(br);
+                       }
+               }
+       }
+
+       struct IMAGE_DATA_DIRECTORY
+       {
+               public DWORD VirtualAddress;
+               public DWORD Size;
+
+               internal void Read(BinaryReader br)
+               {
+                       VirtualAddress = br.ReadUInt32();
+                       Size = br.ReadUInt32();
+               }
+       }
+
+       class SectionHeader
+       {
+               public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
+               public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
+               public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
+               public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
+               public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
+               public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
+
+               public string Name;             // 8 byte UTF8 encoded 0-padded
+               public DWORD VirtualSize;
+               public DWORD VirtualAddress;
+               public DWORD SizeOfRawData;
+               public DWORD PointerToRawData;
+               public DWORD PointerToRelocations;
+               public DWORD PointerToLinenumbers;
+               public WORD NumberOfRelocations;
+               public WORD NumberOfLinenumbers;
+               public DWORD Characteristics;
+
+               internal void Read(BinaryReader br)
+               {
+                       char[] name = new char[8];
+                       int len = 8;
+                       for (int i = 0; i < 8; i++)
+                       {
+                               byte b = br.ReadByte();
+                               name[i] = (char)b;
+                               if (b == 0 && len == 8)
+                               {
+                                       len = i;
+                               }
+                       }
+                       Name = new String(name, 0, len);
+                       VirtualSize = br.ReadUInt32();
+                       VirtualAddress = br.ReadUInt32();
+                       SizeOfRawData = br.ReadUInt32();
+                       PointerToRawData = br.ReadUInt32();
+                       PointerToRelocations = br.ReadUInt32();
+                       PointerToLinenumbers = br.ReadUInt32();
+                       NumberOfRelocations = br.ReadUInt16();
+                       NumberOfLinenumbers = br.ReadUInt16();
+                       Characteristics = br.ReadUInt32();
+               }
+       }
+
+       sealed class PEReader
+       {
+               private MSDOS_HEADER msdos = new MSDOS_HEADER();
+               private IMAGE_NT_HEADERS headers = new IMAGE_NT_HEADERS();
+               private SectionHeader[] sections;
+
+               internal void Read(BinaryReader br)
+               {
+                       msdos.signature = br.ReadUInt16();
+                       br.BaseStream.Seek(58, SeekOrigin.Current);
+                       msdos.peSignatureOffset = br.ReadUInt32();
+
+                       if (msdos.signature != MSDOS_HEADER.MAGIC_MZ)
+                       {
+                               throw new BadImageFormatException();
+                       }
+
+                       br.BaseStream.Seek(msdos.peSignatureOffset, SeekOrigin.Begin);
+                       headers.Read(br);
+                       sections = new SectionHeader[headers.FileHeader.NumberOfSections];
+                       for (int i = 0; i < sections.Length; i++)
+                       {
+                               sections[i] = new SectionHeader();
+                               sections[i].Read(br);
+                       }
+               }
+
+               internal IMAGE_FILE_HEADER FileHeader
+               {
+                       get { return headers.FileHeader; }
+               }
+
+               internal IMAGE_OPTIONAL_HEADER OptionalHeader
+               {
+                       get { return headers.OptionalHeader; }
+               }
+
+               internal DWORD GetComDescriptorVirtualAddress()
+               {
+                       return headers.OptionalHeader.DataDirectory[14].VirtualAddress;
+               }
+
+               internal void GetDataDirectoryEntry(int index, out int rva, out int length)
+               {
+                       rva = (int)headers.OptionalHeader.DataDirectory[index].VirtualAddress;
+                       length = (int)headers.OptionalHeader.DataDirectory[index].Size;
+               }
+
+               internal long RvaToFileOffset(DWORD rva)
+               {
+                       for (int i = 0; i < sections.Length; i++)
+                       {
+                               if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize)
+                               {
+                                       return sections[i].PointerToRawData + rva - sections[i].VirtualAddress;
+                               }
+                       }
+                       throw new BadImageFormatException();
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/PropertyInfoImpl.cs b/mcs/class/IKVM.Reflection/Reader/PropertyInfoImpl.cs
new file mode 100644 (file)
index 0000000..ea95393
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class PropertyInfoImpl : PropertyInfo
+       {
+               private readonly ModuleReader module;
+               private readonly Type declaringType;
+               private readonly int index;
+               private PropertySignature sig;
+               private bool isPublic;
+               private bool isStatic;
+               private bool flagsCached;
+
+               internal PropertyInfoImpl(ModuleReader module, Type declaringType, int index)
+               {
+                       this.module = module;
+                       this.declaringType = declaringType;
+                       this.index = index;
+               }
+
+               public override bool Equals(object obj)
+               {
+                       PropertyInfoImpl other = obj as PropertyInfoImpl;
+                       return other != null && other.DeclaringType == declaringType && other.index == index;
+               }
+
+               public override int GetHashCode()
+               {
+                       return declaringType.GetHashCode() * 77 + index;
+               }
+
+               internal override PropertySignature PropertySignature
+               {
+                       get
+                       {
+                               if (sig == null)
+                               {
+                                       sig = PropertySignature.ReadSig(module, module.GetBlob(module.Property.records[index].Type), declaringType);
+                               }
+                               return sig;
+                       }
+               }
+
+               public override PropertyAttributes Attributes
+               {
+                       get { return (PropertyAttributes)module.Property.records[index].Flags; }
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       return module.Constant.GetRawConstantValue(module, this.MetadataToken);
+               }
+
+               public override bool CanRead
+               {
+                       get { return GetGetMethod(true) != null; }
+               }
+
+               public override bool CanWrite
+               {
+                       get { return GetSetMethod(true) != null; }
+               }
+
+               public override MethodInfo GetGetMethod(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Getter);
+               }
+
+               public override MethodInfo GetSetMethod(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Setter);
+               }
+
+               public override MethodInfo[] GetAccessors(bool nonPublic)
+               {
+                       return module.MethodSemantics.GetMethods(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Getter | MethodSemanticsTable.Setter | MethodSemanticsTable.Other);
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType; }
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return (PropertyTable.Index << 24) + index + 1; }
+               }
+
+               public override string Name
+               {
+                       get { return module.GetString(module.Property.records[index].Name); }
+               }
+
+               internal override bool IsPublic
+               {
+                       get
+                       {
+                               if (!flagsCached)
+                               {
+                                       ComputeFlags();
+                               }
+                               return isPublic;
+                       }
+               }
+
+               internal override bool IsStatic
+               {
+                       get
+                       {
+                               if (!flagsCached)
+                               {
+                                       ComputeFlags();
+                               }
+                               return isStatic;
+                       }
+               }
+
+               private void ComputeFlags()
+               {
+                       module.MethodSemantics.ComputeFlags(module, this.MetadataToken, out isPublic, out isStatic);
+                       flagsCached = true;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/ResourceModule.cs b/mcs/class/IKVM.Reflection/Reader/ResourceModule.cs
new file mode 100644 (file)
index 0000000..e80170d
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class ResourceModule : Module
+       {
+               private readonly Assembly assembly;
+               private readonly string scopeName;
+               private readonly string location;
+
+               internal ResourceModule(Assembly assembly, string scopeName, string location)
+                       : base(assembly.universe)
+               {
+                       this.assembly = assembly;
+                       this.scopeName = scopeName;
+                       this.location = location;
+               }
+
+               public override int MDStreamVersion
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public override bool IsResource()
+               {
+                       return true;
+               }
+
+               public override Assembly Assembly
+               {
+                       get { return assembly; }
+               }
+
+               public override string FullyQualifiedName
+               {
+                       get { return location ?? "<Unknown>"; }
+               }
+
+               public override string Name
+               {
+                       get { return location == null ? "<Unknown>" : System.IO.Path.GetFileName(location); }
+               }
+
+               public override string ScopeName
+               {
+                       get { return scopeName; }
+               }
+
+               public override Guid ModuleVersionId
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override string ResolveString(int metadataToken)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+               {
+                       throw new NotSupportedException();
+               }
+
+               public override AssemblyName[] __GetReferencedAssemblies()
+               {
+                       throw new NotSupportedException();
+               }
+
+               internal override Type GetTypeImpl(string typeName)
+               {
+                       return null;
+               }
+
+               internal override void GetTypesImpl(List<Type> list)
+               {
+               }
+
+               internal override Type GetModuleType()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal override ByteReader GetBlob(int blobIndex)
+               {
+                       throw new InvalidOperationException();
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Reader/TypeDefImpl.cs b/mcs/class/IKVM.Reflection/Reader/TypeDefImpl.cs
new file mode 100644 (file)
index 0000000..ec6aba1
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+       sealed class TypeDefImpl : Type
+       {
+               private readonly ModuleReader module;
+               private readonly int index;
+               private readonly string typeName;
+               private readonly string typeNamespace;
+               private Type[] typeArgs;
+
+               internal TypeDefImpl(ModuleReader module, int index)
+               {
+                       this.module = module;
+                       this.index = index;
+                       this.typeName = TypeNameParser.Escape(module.GetString(module.TypeDef.records[index].TypeName));
+                       this.typeNamespace = TypeNameParser.Escape(module.GetString(module.TypeDef.records[index].TypeNamespace));
+               }
+
+               public override Type BaseType
+               {
+                       get
+                       {
+                               int extends = module.TypeDef.records[index].Extends;
+                               if ((extends & 0xFFFFFF) == 0)
+                               {
+                                       return null;
+                               }
+                               return module.ResolveType(extends, this);
+                       }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return (TypeAttributes)module.TypeDef.records[index].Flags; }
+               }
+
+               public override EventInfo[] __GetDeclaredEvents()
+               {
+                       int token = this.MetadataToken;
+                       // TODO use binary search?
+                       for (int i = 0; i < module.EventMap.records.Length; i++)
+                       {
+                               if (module.EventMap.records[i].Parent == token)
+                               {
+                                       int evt = module.EventMap.records[i].EventList - 1;
+                                       int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length;
+                                       EventInfo[] events = new EventInfo[end - evt];
+                                       for (int j = 0; evt < end; evt++, j++)
+                                       {
+                                               events[j] = new EventInfoImpl(module, this, evt);
+                                       }
+                                       return events;
+                               }
+                       }
+                       return Empty<EventInfo>.Array;
+               }
+
+               public override FieldInfo[] __GetDeclaredFields()
+               {
+                       int field = module.TypeDef.records[index].FieldList - 1;
+                       int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length;
+                       FieldInfo[] fields = new FieldInfo[end - field];
+                       for (int i = 0; field < end; i++, field++)
+                       {
+                               fields[i] = module.GetFieldAt(this, field);
+                       }
+                       return fields;
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       int token = this.MetadataToken;
+                       List<Type> list = new List<Type>();
+                       // TODO use binary search?
+                       for (int i = 0; i < module.InterfaceImpl.records.Length; i++)
+                       {
+                               if (module.InterfaceImpl.records[i].Class == token)
+                               {
+                                       list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public override MethodBase[] __GetDeclaredMethods()
+               {
+                       int method = module.TypeDef.records[index].MethodList - 1;
+                       int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
+                       MethodBase[] methods = new MethodBase[end - method];
+                       for (int i = 0; method < end; method++, i++)
+                       {
+                               methods[i] = module.GetMethodAt(this, method);
+                       }
+                       return methods;
+               }
+
+               public override __MethodImplMap __GetMethodImplMap()
+               {
+                       List<MethodInfo> bodies = new List<MethodInfo>();
+                       List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
+                       int token = this.MetadataToken;
+                       // TODO use binary search?
+                       for (int i = 0; i < module.MethodImpl.records.Length; i++)
+                       {
+                               if (module.MethodImpl.records[i].Class == token)
+                               {
+                                       MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
+                                       int index = bodies.IndexOf(body);
+                                       if (index == -1)
+                                       {
+                                               index = bodies.Count;
+                                               bodies.Add(body);
+                                               declarations.Add(new List<MethodInfo>());
+                                       }
+                                       MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
+                                       declarations[index].Add(declaration);
+                               }
+                       }
+                       __MethodImplMap map = new __MethodImplMap();
+                       map.TargetType = this;
+                       map.MethodBodies = bodies.ToArray();
+                       map.MethodDeclarations = new MethodInfo[declarations.Count][];
+                       for (int i = 0; i < map.MethodDeclarations.Length; i++)
+                       {
+                               map.MethodDeclarations[i] = declarations[i].ToArray();
+                       }
+                       return map;
+               }
+
+               public override Type[] __GetDeclaredTypes()
+               {
+                       int token = this.MetadataToken;
+                       List<Type> list = new List<Type>();
+                       // TODO use binary search?
+                       for (int i = 0; i < module.NestedClass.records.Length; i++)
+                       {
+                               if (module.NestedClass.records[i].EnclosingClass == token)
+                               {
+                                       list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public override PropertyInfo[] __GetDeclaredProperties()
+               {
+                       int token = this.MetadataToken;
+                       // TODO use binary search?
+                       for (int i = 0; i < module.PropertyMap.records.Length; i++)
+                       {
+                               if (module.PropertyMap.records[i].Parent == token)
+                               {
+                                       int property = module.PropertyMap.records[i].PropertyList - 1;
+                                       int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
+                                       PropertyInfo[] properties = new PropertyInfo[end - property];
+                                       for (int j = 0; property < end; property++, j++)
+                                       {
+                                               properties[j] = new PropertyInfoImpl(module, this, property);
+                                       }
+                                       return properties;
+                               }
+                       }
+                       return Empty<PropertyInfo>.Array;
+               }
+
+               public override string Name
+               {
+                       get { return typeName; }
+               }
+
+               public override string Namespace
+               {
+                       get { return typeNamespace; }
+               }
+
+               public override Type UnderlyingSystemType
+               {
+                       get { return this; }
+               }
+
+               public override int MetadataToken
+               {
+                       get { return (TypeDefTable.Index << 24) + index + 1; }
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       PopulateGenericArguments();
+                       return Util.Copy(typeArgs);
+               }
+
+               private void PopulateGenericArguments()
+               {
+                       if (typeArgs == null)
+                       {
+                               int token = this.MetadataToken;
+                               int first = module.GenericParam.FindFirstByOwner(token);
+                               if (first == -1)
+                               {
+                                       typeArgs = Type.EmptyTypes;
+                               }
+                               else
+                               {
+                                       List<Type> list = new List<Type>();
+                                       int len = module.GenericParam.records.Length;
+                                       for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
+                                       {
+                                               list.Add(new GenericTypeParameter(module, i));
+                                       }
+                                       typeArgs = list.ToArray();
+                               }
+                       }
+               }
+
+               internal override Type GetGenericTypeArgument(int index)
+               {
+                       PopulateGenericArguments();
+                       return typeArgs[index];
+               }
+
+               public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+               {
+                       PopulateGenericArguments();
+                       return Util.Copy(new Type[typeArgs.Length][]);
+               }
+
+               public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+               {
+                       PopulateGenericArguments();
+                       return Util.Copy(new Type[typeArgs.Length][]);
+               }
+
+               public override bool IsGenericType
+               {
+                       get { return IsGenericTypeDefinition; }
+               }
+
+               public override bool IsGenericTypeDefinition
+               {
+                       get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
+               }
+
+               public override Type GetGenericTypeDefinition()
+               {
+                       if (IsGenericTypeDefinition)
+                       {
+                               return this;
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               public override string ToString()
+               {
+                       StringBuilder sb = new StringBuilder(this.FullName);
+                       string sep = "[";
+                       foreach (Type arg in GetGenericArguments())
+                       {
+                               sb.Append(sep);
+                               sb.Append(arg);
+                               sep = ",";
+                       }
+                       if (sep != "[")
+                       {
+                               sb.Append(']');
+                       }
+                       return sb.ToString();
+               }
+
+               public override Type DeclaringType
+               {
+                       get
+                       {
+                               // note that we cannot use Type.IsNested for this, because that calls DeclaringType
+                               if ((this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) == 0)
+                               {
+                                       return null;
+                               }
+                               // TODO use binary search (if sorted)
+                               int token = this.MetadataToken;
+                               for (int i = 0; i < module.NestedClass.records.Length; i++)
+                               {
+                                       if (module.NestedClass.records[i].NestedClass == token)
+                                       {
+                                               return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
+                                       }
+                               }
+                               throw new InvalidOperationException();
+                       }
+               }
+
+               public override StructLayoutAttribute StructLayoutAttribute
+               {
+                       get
+                       {
+                               StructLayoutAttribute layout;
+                               switch (this.Attributes & TypeAttributes.LayoutMask)
+                               {
+                                       case TypeAttributes.AutoLayout:
+                                               return null;
+                                       case TypeAttributes.SequentialLayout:
+                                               layout = new StructLayoutAttribute(LayoutKind.Sequential);
+                                               break;
+                                       case TypeAttributes.ExplicitLayout:
+                                               layout = new StructLayoutAttribute(LayoutKind.Explicit);
+                                               break;
+                                       default:
+                                               throw new BadImageFormatException();
+                               }
+                               int token = this.MetadataToken;
+                               // TODO use binary search?
+                               for (int i = 0; i < module.ClassLayout.records.Length; i++)
+                               {
+                                       if (module.ClassLayout.records[i].Parent == token)
+                                       {
+                                               layout.Pack = module.ClassLayout.records[i].PackingSize;
+                                               layout.Size = module.ClassLayout.records[i].ClassSize;
+                                               switch (this.Attributes & TypeAttributes.StringFormatMask)
+                                               {
+                                                       case TypeAttributes.AnsiClass:
+                                                               layout.CharSet = CharSet.Ansi;
+                                                               break;
+                                                       case TypeAttributes.UnicodeClass:
+                                                               layout.CharSet = CharSet.Unicode;
+                                                               break;
+                                                       case TypeAttributes.AutoClass:
+                                                               layout.CharSet = CharSet.Auto;
+                                                               break;
+                                                       default:
+                                                               layout.CharSet = CharSet.None;
+                                                               break;
+                                               }
+                                               return layout;
+                                       }
+                               }
+                               return null;
+                       }
+               }
+
+               public override Module Module
+               {
+                       get { return module; }
+               }
+
+               internal override bool IsModulePseudoType
+               {
+                       get { return index == 0; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Signature.cs b/mcs/class/IKVM.Reflection/Signature.cs
new file mode 100644 (file)
index 0000000..7924c4f
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using CallingConvention = System.Runtime.InteropServices.CallingConvention;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+       abstract class Signature
+       {
+               internal const byte DEFAULT = 0x00;
+               internal const byte VARARG = 0x05;
+               internal const byte GENERIC = 0x10;
+               internal const byte HASTHIS = 0x20;
+               internal const byte EXPLICITTHIS = 0x40;
+               internal const byte FIELD = 0x06;
+               internal const byte LOCAL_SIG = 0x07;
+               internal const byte PROPERTY = 0x08;
+               internal const byte GENERICINST = 0x0A;
+               internal const byte SENTINEL = 0x41;
+               internal const byte ELEMENT_TYPE_VOID = 0x01;
+               internal const byte ELEMENT_TYPE_BOOLEAN = 0x02;
+               internal const byte ELEMENT_TYPE_CHAR = 0x03;
+               internal const byte ELEMENT_TYPE_I1 = 0x04;
+               internal const byte ELEMENT_TYPE_U1 = 0x05;
+               internal const byte ELEMENT_TYPE_I2 = 0x06;
+               internal const byte ELEMENT_TYPE_U2 = 0x07;
+               internal const byte ELEMENT_TYPE_I4 = 0x08;
+               internal const byte ELEMENT_TYPE_U4 = 0x09;
+               internal const byte ELEMENT_TYPE_I8 = 0x0a;
+               internal const byte ELEMENT_TYPE_U8 = 0x0b;
+               internal const byte ELEMENT_TYPE_R4 = 0x0c;
+               internal const byte ELEMENT_TYPE_R8 = 0x0d;
+               internal const byte ELEMENT_TYPE_STRING = 0x0e;
+               internal const byte ELEMENT_TYPE_PTR = 0x0f;
+               internal const byte ELEMENT_TYPE_BYREF = 0x10;
+               internal const byte ELEMENT_TYPE_VALUETYPE = 0x11;
+               internal const byte ELEMENT_TYPE_CLASS = 0x12;
+               internal const byte ELEMENT_TYPE_VAR = 0x13;
+               internal const byte ELEMENT_TYPE_ARRAY = 0x14;
+               internal const byte ELEMENT_TYPE_GENERICINST = 0x15;
+               internal const byte ELEMENT_TYPE_TYPEDBYREF = 0x16;
+               internal const byte ELEMENT_TYPE_I = 0x18;
+               internal const byte ELEMENT_TYPE_U = 0x19;
+               internal const byte ELEMENT_TYPE_FNPTR = 0x1b;
+               internal const byte ELEMENT_TYPE_OBJECT = 0x1c;
+               internal const byte ELEMENT_TYPE_SZARRAY = 0x1d;
+               internal const byte ELEMENT_TYPE_MVAR = 0x1e;
+               internal const byte ELEMENT_TYPE_CMOD_REQD = 0x1f;
+               internal const byte ELEMENT_TYPE_CMOD_OPT = 0x20;
+               internal const byte ELEMENT_TYPE_PINNED = 0x45;
+
+               internal abstract void WriteSig(ModuleBuilder module, ByteBuffer bb);
+
+               private static Type ReadGenericInst(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       switch (br.ReadByte())
+                       {
+                               case ELEMENT_TYPE_CLASS:
+                               case ELEMENT_TYPE_VALUETYPE:
+                                       break;
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+                       Type type = ReadTypeDefOrRefEncoded(module, br, context);
+                       if (!type.IsGenericTypeDefinition)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       int genArgCount = br.ReadCompressedInt();
+                       Type[] args = new Type[genArgCount];
+                       Type[][] reqmod = null;
+                       Type[][] optmod = null;
+                       for (int i = 0; i < genArgCount; i++)
+                       {
+                               // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for genericinst, but C++ uses it, the verifier allows it and ildasm also supports it
+                               CustomModifiers mods = ReadCustomModifiers(module, br, context);
+                               if (mods.required != null || mods.optional != null)
+                               {
+                                       if (reqmod == null)
+                                       {
+                                               reqmod = new Type[genArgCount][];
+                                               optmod = new Type[genArgCount][];
+                                       }
+                                       reqmod[i] = mods.required;
+                                       optmod[i] = mods.optional;
+                               }
+                               args[i] = ReadType(module, br, context);
+                       }
+                       return GenericTypeInstance.Make(type, args, reqmod, optmod);
+               }
+
+               internal static Type ReadTypeSpec(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       // LAMESPEC a TypeSpec can contain custom modifiers (C++/CLI generates "newarr (TypeSpec with custom modifiers)")
+                       SkipCustomModifiers(br);
+                       // LAMESPEC anything can be adorned by (useless) custom modifiers
+                       // also, VAR and MVAR are also used in TypeSpec (contrary to what the spec says)
+                       return ReadType(module, br, context);
+               }
+
+               private static Type ReadFunctionPointer(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       // TODO like .NET we return System.IntPtr here, but ideally we should fire an event in Universe that
+                       // the user can hook to provide a custom type (or we simply should build in full support for function pointer types)
+                       MethodSignature.ReadStandAloneMethodSig(module, br, context);
+                       return module.universe.System_IntPtr;
+               }
+
+               internal static Type[] ReadMethodSpec(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       if (br.ReadByte() != GENERICINST)
+                       {
+                               throw new BadImageFormatException();
+                       }
+                       Type[] args = new Type[br.ReadCompressedInt()];
+                       for (int i = 0; i < args.Length; i++)
+                       {
+                               args[i] = ReadType(module, br, context);
+                       }
+                       return args;
+               }
+
+               private static int ReadArrayShape(ByteReader br)
+               {
+                       int rank = br.ReadCompressedInt();
+                       int numSizes = br.ReadCompressedInt();
+                       for (int i = 0; i < numSizes; i++)
+                       {
+                               br.ReadCompressedInt();
+                       }
+                       int numLoBounds = br.ReadCompressedInt();
+                       for (int i = 0; i < numLoBounds; i++)
+                       {
+                               br.ReadCompressedInt();
+                       }
+                       return rank;
+               }
+
+               private static Type ReadTypeOrVoid(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       if (br.PeekByte() == ELEMENT_TYPE_VOID)
+                       {
+                               br.ReadByte();
+                               return module.universe.System_Void;
+                       }
+                       else
+                       {
+                               return ReadType(module, br, context);
+                       }
+               }
+
+               // see ECMA 335 CLI spec June 2006 section 23.2.12 for this production
+               protected static Type ReadType(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       CustomModifiers mods;
+                       switch (br.ReadByte())
+                       {
+                               case ELEMENT_TYPE_CLASS:
+                               case ELEMENT_TYPE_VALUETYPE:
+                                       return ReadTypeDefOrRefEncoded(module, br, context);
+                               case ELEMENT_TYPE_BOOLEAN:
+                                       return module.universe.System_Boolean;
+                               case ELEMENT_TYPE_CHAR:
+                                       return module.universe.System_Char;
+                               case ELEMENT_TYPE_I1:
+                                       return module.universe.System_SByte;
+                               case ELEMENT_TYPE_U1:
+                                       return module.universe.System_Byte;
+                               case ELEMENT_TYPE_I2:
+                                       return module.universe.System_Int16;
+                               case ELEMENT_TYPE_U2:
+                                       return module.universe.System_UInt16;
+                               case ELEMENT_TYPE_I4:
+                                       return module.universe.System_Int32;
+                               case ELEMENT_TYPE_U4:
+                                       return module.universe.System_UInt32;
+                               case ELEMENT_TYPE_I8:
+                                       return module.universe.System_Int64;
+                               case ELEMENT_TYPE_U8:
+                                       return module.universe.System_UInt64;
+                               case ELEMENT_TYPE_R4:
+                                       return module.universe.System_Single;
+                               case ELEMENT_TYPE_R8:
+                                       return module.universe.System_Double;
+                               case ELEMENT_TYPE_I:
+                                       return module.universe.System_IntPtr;
+                               case ELEMENT_TYPE_U:
+                                       return module.universe.System_UIntPtr;
+                               case ELEMENT_TYPE_STRING:
+                                       return module.universe.System_String;
+                               case ELEMENT_TYPE_OBJECT:
+                                       return module.universe.System_Object;
+                               case ELEMENT_TYPE_VAR:
+                                       return context.GetGenericTypeArgument(br.ReadCompressedInt());
+                               case ELEMENT_TYPE_MVAR:
+                                       return context.GetGenericMethodArgument(br.ReadCompressedInt());
+                               case ELEMENT_TYPE_GENERICINST:
+                                       return ReadGenericInst(module, br, context);
+                               case ELEMENT_TYPE_SZARRAY:
+                                       mods = ReadCustomModifiers(module, br, context);
+                                       return ReadType(module, br, context).__MakeArrayType(mods.required, mods.optional);
+                               case ELEMENT_TYPE_ARRAY:
+                                       mods = ReadCustomModifiers(module, br, context);
+                                       return ReadType(module, br, context).__MakeArrayType(ReadArrayShape(br), mods.required, mods.optional);
+                               case ELEMENT_TYPE_PTR:
+                                       mods = ReadCustomModifiers(module, br, context);
+                                       return ReadTypeOrVoid(module, br, context).__MakePointerType(mods.required, mods.optional);
+                               case ELEMENT_TYPE_FNPTR:
+                                       return ReadFunctionPointer(module, br, context);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               internal static void ReadLocalVarSig(ModuleReader module, ByteReader br, IGenericContext context, List<LocalVariableInfo> list)
+               {
+                       if (br.Length < 2 || br.ReadByte() != LOCAL_SIG)
+                       {
+                               throw new BadImageFormatException("Invalid local variable signature");
+                       }
+                       int count = br.ReadCompressedInt();
+                       for (int i = 0; i < count; i++)
+                       {
+                               if (br.PeekByte() == ELEMENT_TYPE_TYPEDBYREF)
+                               {
+                                       br.ReadByte();
+                                       list.Add(new LocalVariableInfo(i, module.universe.System_TypedReference, false));
+                               }
+                               else
+                               {
+                                       SkipCustomModifiers(br);
+                                       bool pinned = false;
+                                       if (br.PeekByte() == ELEMENT_TYPE_PINNED)
+                                       {
+                                               br.ReadByte();
+                                               pinned = true;
+                                       }
+                                       SkipCustomModifiers(br);
+                                       Type type = ReadTypeOrByRef(module, br, context);
+                                       list.Add(new LocalVariableInfo(i, type, pinned));
+                               }
+                       }
+               }
+
+               private static Type ReadTypeOrByRef(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       if (br.PeekByte() == ELEMENT_TYPE_BYREF)
+                       {
+                               br.ReadByte();
+                               // LAMESPEC it is allowed (by C++/CLI, ilasm and peverify) to have custom modifiers after the BYREF
+                               // (which makes sense, as it is analogous to pointers)
+                               CustomModifiers mods = ReadCustomModifiers(module, br, context);
+                               // C++/CLI generates void& local variables, so we need to use ReadTypeOrVoid here
+                               return ReadTypeOrVoid(module, br, context).__MakeByRefType(mods.required, mods.optional);
+                       }
+                       else
+                       {
+                               return ReadType(module, br, context);
+                       }
+               }
+
+               protected static Type ReadRetType(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       switch (br.PeekByte())
+                       {
+                               case ELEMENT_TYPE_VOID:
+                                       br.ReadByte();
+                                       return module.universe.System_Void;
+                               case ELEMENT_TYPE_TYPEDBYREF:
+                                       br.ReadByte();
+                                       return module.universe.System_TypedReference;
+                               default:
+                                       return ReadTypeOrByRef(module, br, context);
+                       }
+               }
+
+               protected static Type ReadParam(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       switch (br.PeekByte())
+                       {
+                               case ELEMENT_TYPE_TYPEDBYREF:
+                                       br.ReadByte();
+                                       return module.universe.System_TypedReference;
+                               default:
+                                       return ReadTypeOrByRef(module, br, context);
+                       }
+               }
+
+               protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type)
+               {
+                       while (type.HasElementType)
+                       {
+                               if (type.__IsVector)
+                               {
+                                       bb.Write(ELEMENT_TYPE_SZARRAY);
+                               }
+                               else if (type.IsArray)
+                               {
+                                       int rank = type.GetArrayRank();
+                                       bb.Write(ELEMENT_TYPE_ARRAY);
+                                       // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it
+                                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers());
+                                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers());
+                                       WriteType(module, bb, type.GetElementType());
+                                       bb.WriteCompressedInt(rank);
+                                       // since a Type doesn't contain the lower/upper bounds
+                                       // (they act like a custom modifier, so they are part of the signature, but not of the Type),
+                                       // we set them to the C# compatible values and hope for the best
+                                       bb.WriteCompressedInt(0);       // boundsCount
+                                       bb.WriteCompressedInt(rank);    // loCount
+                                       for (int i = 0; i < rank; i++)
+                                       {
+                                               bb.WriteCompressedInt(0);
+                                       }
+                                       return;
+                               }
+                               else if (type.IsByRef)
+                               {
+                                       bb.Write(ELEMENT_TYPE_BYREF);
+                               }
+                               else if (type.IsPointer)
+                               {
+                                       bb.Write(ELEMENT_TYPE_PTR);
+                               }
+                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers());
+                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers());
+                               type = type.GetElementType();
+                       }
+                       Universe u = module.universe;
+                       if (type == u.System_Void)
+                       {
+                               bb.Write(ELEMENT_TYPE_VOID);
+                       }
+                       else if (type == u.System_Boolean)
+                       {
+                               bb.Write(ELEMENT_TYPE_BOOLEAN);
+                       }
+                       else if (type == u.System_Char)
+                       {
+                               bb.Write(ELEMENT_TYPE_CHAR);
+                       }
+                       else if (type == u.System_SByte)
+                       {
+                               bb.Write(ELEMENT_TYPE_I1);
+                       }
+                       else if (type == u.System_Byte)
+                       {
+                               bb.Write(ELEMENT_TYPE_U1);
+                       }
+                       else if (type == u.System_Int16)
+                       {
+                               bb.Write(ELEMENT_TYPE_I2);
+                       }
+                       else if (type == u.System_UInt16)
+                       {
+                               bb.Write(ELEMENT_TYPE_U2);
+                       }
+                       else if (type == u.System_Int32)
+                       {
+                               bb.Write(ELEMENT_TYPE_I4);
+                       }
+                       else if (type == u.System_UInt32)
+                       {
+                               bb.Write(ELEMENT_TYPE_U4);
+                       }
+                       else if (type == u.System_Int64)
+                       {
+                               bb.Write(ELEMENT_TYPE_I8);
+                       }
+                       else if (type == u.System_UInt64)
+                       {
+                               bb.Write(ELEMENT_TYPE_U8);
+                       }
+                       else if (type == u.System_Single)
+                       {
+                               bb.Write(ELEMENT_TYPE_R4);
+                       }
+                       else if (type == u.System_Double)
+                       {
+                               bb.Write(ELEMENT_TYPE_R8);
+                       }
+                       else if (type == u.System_String)
+                       {
+                               bb.Write(ELEMENT_TYPE_STRING);
+                       }
+                       else if (type == u.System_IntPtr)
+                       {
+                               bb.Write(ELEMENT_TYPE_I);
+                       }
+                       else if (type == u.System_UIntPtr)
+                       {
+                               bb.Write(ELEMENT_TYPE_U);
+                       }
+                       else if (type == u.System_TypedReference)
+                       {
+                               bb.Write(ELEMENT_TYPE_TYPEDBYREF);
+                       }
+                       else if (type == u.System_Object)
+                       {
+                               bb.Write(ELEMENT_TYPE_OBJECT);
+                       }
+                       else if (type.IsGenericParameter)
+                       {
+                               if (type is UnboundGenericMethodParameter || type.DeclaringMethod != null)
+                               {
+                                       bb.Write(ELEMENT_TYPE_MVAR);
+                               }
+                               else
+                               {
+                                       bb.Write(ELEMENT_TYPE_VAR);
+                               }
+                               bb.WriteCompressedInt(type.GenericParameterPosition);
+                       }
+                       else if (type.IsGenericType)
+                       {
+                               WriteGenericSignature(module, bb, type);
+                       }
+                       else
+                       {
+                               if (type.IsValueType)
+                               {
+                                       bb.Write(ELEMENT_TYPE_VALUETYPE);
+                               }
+                               else
+                               {
+                                       bb.Write(ELEMENT_TYPE_CLASS);
+                               }
+                               bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
+                       }
+               }
+
+               private static void WriteGenericSignature(ModuleBuilder module, ByteBuffer bb, Type type)
+               {
+                       Type[] typeArguments = type.GetGenericArguments();
+                       Type[][] requiredCustomModifiers = type.__GetGenericArgumentsRequiredCustomModifiers();
+                       Type[][] optionalCustomModifiers = type.__GetGenericArgumentsOptionalCustomModifiers();
+                       if (!type.IsGenericTypeDefinition)
+                       {
+                               type = type.GetGenericTypeDefinition();
+                       }
+                       bb.Write(ELEMENT_TYPE_GENERICINST);
+                       if (type.IsValueType)
+                       {
+                               bb.Write(ELEMENT_TYPE_VALUETYPE);
+                       }
+                       else
+                       {
+                               bb.Write(ELEMENT_TYPE_CLASS);
+                       }
+                       bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
+                       bb.WriteCompressedInt(typeArguments.Length);
+                       for (int i = 0; i < typeArguments.Length; i++)
+                       {
+                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers[i]);
+                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers[i]);
+                               WriteType(module, bb, typeArguments[i]);
+                       }
+               }
+
+               protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, byte mod, Type[] modifiers)
+               {
+                       if (modifiers != null)
+                       {
+                               foreach (Type type in modifiers)
+                               {
+                                       bb.Write(mod);
+                                       bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(type));
+                               }
+                       }
+               }
+
+               protected static bool IsCustomModifier(byte b)
+               {
+                       return b == ELEMENT_TYPE_CMOD_OPT || b == ELEMENT_TYPE_CMOD_REQD;
+               }
+
+               struct CustomModifiers
+               {
+                       internal Type[] required;
+                       internal Type[] optional;
+               }
+
+               private static CustomModifiers ReadCustomModifiers(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       CustomModifiers mods = new CustomModifiers();
+                       byte b = br.PeekByte();
+                       if (IsCustomModifier(b))
+                       {
+                               List<Type> required = new List<Type>();
+                               List<Type> optional = new List<Type>();
+                               while (IsCustomModifier(b))
+                               {
+                                       bool req = br.ReadByte() == ELEMENT_TYPE_CMOD_REQD;
+                                       Type type = ReadTypeDefOrRefEncoded(module, br, context);
+                                       (req ? required : optional).Add(type);
+                                       b = br.PeekByte();
+                               }
+                               mods.required = required.ToArray();
+                               mods.optional = optional.ToArray();
+                       }
+                       return mods;
+               }
+
+               protected static void SkipCustomModifiers(ByteReader br)
+               {
+                       byte b = br.PeekByte();
+                       while (IsCustomModifier(b))
+                       {
+                               br.ReadByte();
+                               br.ReadCompressedInt();
+                               b = br.PeekByte();
+                       }
+               }
+
+               private static Type ReadTypeDefOrRefEncoded(ModuleReader module, ByteReader br, IGenericContext context)
+               {
+                       int encoded = br.ReadCompressedInt();
+                       switch (encoded & 3)
+                       {
+                               case 0:
+                                       return module.ResolveType((TypeDefTable.Index << 24) + (encoded >> 2), null, null);
+                               case 1:
+                                       return module.ResolveType((TypeRefTable.Index << 24) + (encoded >> 2), null, null);
+                               case 2:
+                                       return module.ResolveType((TypeSpecTable.Index << 24) + (encoded >> 2), context);
+                               default:
+                                       throw new BadImageFormatException();
+                       }
+               }
+
+               protected static void ReadCustomModifiers(ModuleReader module, ByteReader br, IGenericContext context, out Type[] requiredCustomModifiers, out Type[] optionalCustomModifiers)
+               {
+                       byte b = br.PeekByte();
+                       if (IsCustomModifier(b))
+                       {
+                               List<Type> required = new List<Type>();
+                               List<Type> optional = new List<Type>();
+                               while (IsCustomModifier(b))
+                               {
+                                       br.ReadByte();
+                                       Type type = ReadTypeDefOrRefEncoded(module, br, context);
+                                       if (b == ELEMENT_TYPE_CMOD_REQD)
+                                       {
+                                               required.Add(type);
+                                       }
+                                       else
+                                       {
+                                               optional.Add(type);
+                                       }
+                                       b = br.PeekByte();
+                               }
+                               requiredCustomModifiers = required.ToArray();
+                               optionalCustomModifiers = optional.ToArray();
+                       }
+                       else
+                       {
+                               requiredCustomModifiers = null;
+                               optionalCustomModifiers = null;
+                       }
+               }
+
+               // unmanaged calling convention
+               internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
+               {
+                       switch (callingConvention)
+                       {
+                               case CallingConvention.Cdecl:
+                                       bb.Write((byte)0x01);   // C
+                                       break;
+                               case CallingConvention.StdCall:
+                               case CallingConvention.Winapi:
+                                       bb.Write((byte)0x02);   // STDCALL
+                                       break;
+                               case CallingConvention.ThisCall:
+                                       bb.Write((byte)0x03);   // THISCALL
+                                       break;
+                               case CallingConvention.FastCall:
+                                       bb.Write((byte)0x04);   // FASTCALL
+                                       break;
+                               default:
+                                       throw new ArgumentOutOfRangeException("callingConvention");
+                       }
+                       bb.WriteCompressedInt(parameterTypes.Length);
+                       WriteType(module, bb, returnType);
+                       foreach (Type t in parameterTypes)
+                       {
+                               WriteType(module, bb, t);
+                       }
+               }
+
+               // managed calling convention
+               internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+               {
+                       byte flags = 0;
+                       if ((callingConvention & CallingConventions.HasThis) != 0)
+                       {
+                               flags |= HASTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+                       {
+                               flags |= EXPLICITTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.VarArgs) != 0)
+                       {
+                               flags |= VARARG;
+                       }
+                       bb.Write(flags);
+                       bb.WriteCompressedInt(parameterTypes.Length + optionalParameterTypes.Length);
+                       WriteType(module, bb, returnType);
+                       foreach (Type t in parameterTypes)
+                       {
+                               WriteType(module, bb, t);
+                       }
+                       if (optionalParameterTypes.Length > 0)
+                       {
+                               bb.Write(SENTINEL);
+                               foreach (Type t in optionalParameterTypes)
+                               {
+                                       WriteType(module, bb, t);
+                               }
+                       }
+               }
+
+               internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals)
+               {
+                       bb.Write(LOCAL_SIG);
+                       bb.WriteCompressedInt(locals.Count);
+                       foreach (LocalBuilder local in locals)
+                       {
+                               if (local.IsPinned)
+                               {
+                                       bb.Write(ELEMENT_TYPE_PINNED);
+                               }
+                               WriteType(module, bb, local.LocalType);
+                       }
+               }
+
+               internal static void WritePropertySig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention,
+                       Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+                       Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       byte flags = PROPERTY;
+                       if ((callingConvention & CallingConventions.HasThis) != 0)
+                       {
+                               flags |= HASTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+                       {
+                               flags |= EXPLICITTHIS;
+                       }
+                       if ((callingConvention & CallingConventions.VarArgs) != 0)
+                       {
+                               flags |= VARARG;
+                       }
+                       bb.Write(flags);
+                       bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
+                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, returnTypeRequiredCustomModifiers);
+                       WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, returnTypeOptionalCustomModifiers);
+                       WriteType(module, bb, returnType);
+                       if (parameterTypes != null)
+                       {
+                               for (int i = 0; i < parameterTypes.Length; i++)
+                               {
+                                       if (parameterTypeRequiredCustomModifiers != null)
+                                       {
+                                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterTypeRequiredCustomModifiers[i]);
+                                       }
+                                       if (parameterTypeOptionalCustomModifiers != null)
+                                       {
+                                               WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterTypeOptionalCustomModifiers[i]);
+                                       }
+                                       WriteType(module, bb, parameterTypes[i]);
+                               }
+                       }
+               }
+
+               internal static void WriteTypeSpec(ModuleBuilder module, ByteBuffer bb, Type type)
+               {
+                       WriteType(module, bb, type);
+               }
+
+               internal static void WriteMethodSpec(ModuleBuilder module, ByteBuffer bb, Type[] genArgs)
+               {
+                       bb.Write(GENERICINST);
+                       bb.WriteCompressedInt(genArgs.Length);
+                       foreach (Type arg in genArgs)
+                       {
+                               WriteType(module, bb, arg);
+                       }
+               }
+
+               // this reads just the optional parameter types, from a MethodRefSig
+               internal static Type[] ReadOptionalParameterTypes(ModuleReader module, ByteReader br)
+               {
+                       br.ReadByte();
+                       int paramCount = br.ReadCompressedInt();
+                       SkipCustomModifiers(br);
+                       ReadRetType(module, br, null);
+                       for (int i = 0; i < paramCount; i++)
+                       {
+                               if (br.PeekByte() == SENTINEL)
+                               {
+                                       br.ReadByte();
+                                       Type[] types = new Type[paramCount - i];
+                                       for (int j = 0; j < types.Length; j++)
+                                       {
+                                               SkipCustomModifiers(br);
+                                               types[j] = ReadType(module, br, null);
+                                       }
+                                       return types;
+                               }
+                               SkipCustomModifiers(br);
+                               ReadType(module, br, null);
+                       }
+                       return Type.EmptyTypes;
+               }
+
+               protected static Type[] BindTypeParameters(IGenericBinder binder, Type[] types)
+               {
+                       if (types == null || types.Length == 0)
+                       {
+                               return Type.EmptyTypes;
+                       }
+                       Type[] expanded = new Type[types.Length];
+                       for (int i = 0; i < types.Length; i++)
+                       {
+                               expanded[i] = types[i].BindTypeParameters(binder);
+                       }
+                       return expanded;
+               }
+
+               protected static Type[][] BindTypeParameters(IGenericBinder binder, Type[][] types)
+               {
+                       if (types == null)
+                       {
+                               return null;
+                       }
+                       Type[][] expanded = new Type[types.Length][];
+                       for (int i = 0; i < types.Length; i++)
+                       {
+                               expanded[i] = BindTypeParameters(binder, types[i]);
+                       }
+                       return expanded;
+               }
+
+               protected static Type[][][] BindTypeParameters(IGenericBinder binder, Type[][][] types)
+               {
+                       if (types == null)
+                       {
+                               return null;
+                       }
+                       Type[][][] expanded = new Type[types.Length][][];
+                       for (int i = 0; i < types.Length; i++)
+                       {
+                               expanded[i] = BindTypeParameters(binder, types[i]);
+                       }
+                       return expanded;
+               }
+
+               protected static Type[] BindTypeParameters(IGenericBinder binder, Type[][][] types, int index, int optOrReq)
+               {
+                       if (types == null || types[index] == null)
+                       {
+                               return null;
+                       }
+                       return BindTypeParameters(binder, types[index][optOrReq]);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/StandAloneMethodSig.cs b/mcs/class/IKVM.Reflection/StandAloneMethodSig.cs
new file mode 100644 (file)
index 0000000..007e575
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+       public sealed class __StandAloneMethodSig
+       {
+               private readonly bool unmanaged;
+               private readonly CallingConvention unmanagedCallingConvention;
+               private readonly CallingConventions callingConvention;
+               private readonly Type returnType;
+               private readonly Type[] parameterTypes;
+               private readonly Type[] optionalParameterTypes;
+
+               internal __StandAloneMethodSig(bool unmanaged, CallingConvention unmanagedCallingConvention, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+               {
+                       this.unmanaged = unmanaged;
+                       this.unmanagedCallingConvention = unmanagedCallingConvention;
+                       this.callingConvention = callingConvention;
+                       this.returnType = returnType;
+                       this.parameterTypes = parameterTypes;
+                       this.optionalParameterTypes = optionalParameterTypes;
+               }
+
+               public bool IsUnmanaged
+               {
+                       get { return unmanaged; }
+               }
+
+               public CallingConventions CallingConvention
+               {
+                       get { return callingConvention; }
+               }
+
+               public CallingConvention UnmanagedCallingConvention
+               {
+                       get { return unmanagedCallingConvention; }
+               }
+
+               public Type ReturnType
+               {
+                       get { return returnType; }
+               }
+
+               public Type[] ParameterTypes
+               {
+                       get { return Util.Copy(parameterTypes); }
+               }
+
+               public Type[] OptionalParameterTypes
+               {
+                       get { return Util.Copy(optionalParameterTypes); }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/StrongNameKeyPair.cs b/mcs/class/IKVM.Reflection/StrongNameKeyPair.cs
new file mode 100644 (file)
index 0000000..6ea6f7e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       public class StrongNameKeyPair
+       {
+               internal readonly System.Reflection.StrongNameKeyPair keyPair;
+
+               internal StrongNameKeyPair(System.Reflection.StrongNameKeyPair keyPair)
+               {
+                       this.keyPair = keyPair;
+               }
+
+               public StrongNameKeyPair(string keyPairContainer)
+               {
+                       this.keyPair = new System.Reflection.StrongNameKeyPair(keyPairContainer);
+               }
+
+               public StrongNameKeyPair(byte[] keyPairArray)
+               {
+                       this.keyPair = new System.Reflection.StrongNameKeyPair(keyPairArray);
+               }
+
+               public StrongNameKeyPair(System.IO.FileStream fs)
+               {
+                       this.keyPair = new System.Reflection.StrongNameKeyPair(fs);
+               }
+
+               public byte[] PublicKey
+               {
+                       get { return keyPair.PublicKey; }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Type.cs b/mcs/class/IKVM.Reflection/Type.cs
new file mode 100644 (file)
index 0000000..43ed271
--- /dev/null
@@ -0,0 +1,2398 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Collections.Generic;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection
+{
+       interface IGenericContext
+       {
+               Type GetGenericTypeArgument(int index);
+               Type GetGenericMethodArgument(int index);
+       }
+
+       interface IGenericBinder
+       {
+               Type BindTypeParameter(Type type);
+               Type BindMethodParameter(Type type);
+       }
+
+       public abstract class Type : MemberInfo, IGenericContext, IGenericBinder
+       {
+               public static readonly Type[] EmptyTypes = Empty<Type>.Array;
+
+               public static Binder DefaultBinder
+               {
+                       get { return null; }
+               }
+
+               public sealed override MemberTypes MemberType
+               {
+                       get { return IsNested ? MemberTypes.NestedType : MemberTypes.TypeInfo; }
+               }
+
+               public virtual string AssemblyQualifiedName
+               {
+                       // NOTE the assembly name is not escaped here, only when used in a generic type instantiation
+                       get { return this.FullName + ", " + this.Assembly.FullName; }
+               }
+
+               public abstract Type BaseType
+               {
+                       get;
+               }
+
+               public abstract TypeAttributes Attributes
+               {
+                       get;
+               }
+
+               public virtual Type GetElementType()
+               {
+                       return null;
+               }
+
+               internal virtual void CheckBaked()
+               {
+               }
+
+               public virtual Type[] __GetDeclaredTypes()
+               {
+                       return Type.EmptyTypes;
+               }
+
+               public virtual Type[] __GetDeclaredInterfaces()
+               {
+                       return Type.EmptyTypes;
+               }
+
+               public virtual MethodBase[] __GetDeclaredMethods()
+               {
+                       return Empty<MethodBase>.Array;
+               }
+
+               public virtual __MethodImplMap __GetMethodImplMap()
+               {
+                       throw new NotSupportedException();
+               }
+
+               public virtual FieldInfo[] __GetDeclaredFields()
+               {
+                       return Empty<FieldInfo>.Array;
+               }
+
+               public virtual EventInfo[] __GetDeclaredEvents()
+               {
+                       return Empty<EventInfo>.Array;
+               }
+
+               public virtual PropertyInfo[] __GetDeclaredProperties()
+               {
+                       return Empty<PropertyInfo>.Array;
+               }
+
+               public virtual Type[] __GetRequiredCustomModifiers()
+               {
+                       return Type.EmptyTypes;
+               }
+
+               public virtual Type[] __GetOptionalCustomModifiers()
+               {
+                       return Type.EmptyTypes;
+               }
+
+               public virtual bool HasElementType
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsArray
+               {
+                       get { return false; }
+               }
+
+               public virtual bool __IsVector
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsByRef
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsPointer
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsValueType
+               {
+                       get
+                       {
+                               Type baseType = this.BaseType;
+                               return baseType == this.Module.universe.System_Enum
+                                       || (baseType == this.Module.universe.System_ValueType && this != this.Module.universe.System_Enum);
+                       }
+               }
+
+               public virtual bool IsGenericParameter
+               {
+                       get { return false; }
+               }
+
+               public virtual int GenericParameterPosition
+               {
+                       get { throw new NotSupportedException(); }
+               }
+
+               public virtual MethodBase DeclaringMethod
+               {
+                       get { return null; }
+               }
+
+               public virtual Type UnderlyingSystemType
+               {
+                       get { return this; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return null; }
+               }
+
+               public override string Name
+               {
+                       get
+                       {
+                               string fullname = FullName;
+                               return fullname.Substring(fullname.LastIndexOf('.') + 1);
+                       }
+               }
+
+               public virtual string Namespace
+               {
+                       get
+                       {
+                               if (IsNested)
+                               {
+                                       return null;
+                               }
+                               string fullname = FullName;
+                               int index = fullname.LastIndexOf('.');
+                               return index < 0 ? null : fullname.Substring(0, index);
+                       }
+               }
+
+               internal virtual int GetModuleBuilderToken()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public bool Equals(Type type)
+               {
+                       return !ReferenceEquals(type, null) && ReferenceEquals(type.UnderlyingSystemType, this.UnderlyingSystemType);
+               }
+
+               public override bool Equals(object obj)
+               {
+                       return Equals(obj as Type);
+               }
+
+               public override int GetHashCode()
+               {
+                       Type type = this.UnderlyingSystemType;
+                       return ReferenceEquals(type, this) ? base.GetHashCode() : type.GetHashCode();
+               }
+
+               public virtual Type[] GetGenericArguments()
+               {
+                       return Type.EmptyTypes;
+               }
+
+               public virtual Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+               {
+                       return Empty<Type[]>.Array;
+               }
+
+               public virtual Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+               {
+                       return Empty<Type[]>.Array;
+               }
+
+               public virtual Type GetGenericTypeDefinition()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public virtual StructLayoutAttribute StructLayoutAttribute
+               {
+                       get { return null; }
+               }
+
+               public virtual bool IsGenericType
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsGenericTypeDefinition
+               {
+                       get { return false; }
+               }
+
+               public virtual bool ContainsGenericParameters
+               {
+                       get
+                       {
+                               if (this.IsGenericParameter)
+                               {
+                                       return true;
+                               }
+                               foreach (Type arg in this.GetGenericArguments())
+                               {
+                                       if (arg.ContainsGenericParameters)
+                                       {
+                                               return true;
+                                       }
+                               }
+                               return false;
+                       }
+               }
+
+               public virtual Type[] GetGenericParameterConstraints()
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public virtual GenericParameterAttributes GenericParameterAttributes
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public virtual int GetArrayRank()
+               {
+                       throw new NotSupportedException();
+               }
+
+               // .NET 4.0 API
+               public virtual Type GetEnumUnderlyingType()
+               {
+                       if (!this.IsEnum)
+                       {
+                               throw new ArgumentException();
+                       }
+                       CheckBaked();
+                       return GetEnumUnderlyingTypeImpl();
+               }
+
+               internal Type GetEnumUnderlyingTypeImpl()
+               {
+                       foreach (FieldInfo field in __GetDeclaredFields())
+                       {
+                               if (!field.IsStatic)
+                               {
+                                       // the CLR assumes that an enum has only one instance field, so we can do the same
+                                       return field.FieldType;
+                               }
+                       }
+                       throw new InvalidOperationException();
+               }
+
+               public override string ToString()
+               {
+                       return FullName;
+               }
+
+               public virtual string FullName
+               {
+                       get
+                       {
+                               Type decl = this.DeclaringType;
+                               string ns = this.Namespace;
+                               if (ns == null)
+                               {
+                                       if (decl == null)
+                                       {
+                                               return this.Name;
+                                       }
+                                       else
+                                       {
+                                               return decl.FullName + "+" + this.Name;
+                                       }
+                               }
+                               else
+                               {
+                                       if (decl == null)
+                                       {
+                                               return ns + "." + this.Name;
+                                       }
+                                       else
+                                       {
+                                               return decl.FullName + "+" + ns + "." + this.Name;
+                                       }
+                               }
+                       }
+               }
+
+               internal virtual bool IsModulePseudoType
+               {
+                       get { return false; }
+               }
+
+               internal virtual Type GetGenericTypeArgument(int index)
+               {
+                       throw new InvalidOperationException();
+               }
+
+               public MemberInfo[] GetDefaultMembers()
+               {
+                       Type defaultMemberAttribute = this.Module.universe.Import(typeof(System.Reflection.DefaultMemberAttribute));
+                       foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(this))
+                       {
+                               if (cad.Constructor.DeclaringType.Equals(defaultMemberAttribute))
+                               {
+                                       return GetMember((string)cad.ConstructorArguments[0].Value);
+                               }
+                       }
+                       return Empty<MemberInfo>.Array;
+               }
+
+               public MemberInfo[] GetMember(string name)
+               {
+                       return GetMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
+               {
+                       return GetMember(name, MemberTypes.All, bindingAttr);
+               }
+
+               public MemberInfo[] GetMembers()
+               {
+                       return GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public MemberInfo[] GetMembers(BindingFlags bindingAttr)
+               {
+                       List<MemberInfo> members = new List<MemberInfo>();
+                       members.AddRange(GetConstructors(bindingAttr));
+                       members.AddRange(GetMethods(bindingAttr));
+                       members.AddRange(GetFields(bindingAttr));
+                       members.AddRange(GetProperties(bindingAttr));
+                       members.AddRange(GetEvents(bindingAttr));
+                       members.AddRange(GetNestedTypes(bindingAttr));
+                       return members.ToArray();
+               }
+
+               public MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
+               {
+                       MemberFilter filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.Equals(filterCriteria); };
+                       return FindMembers(type, bindingAttr, filter, name);
+               }
+
+               private static void AddMembers(List<MemberInfo> list, MemberFilter filter, object filterCriteria, MemberInfo[] members)
+               {
+                       foreach (MemberInfo member in members)
+                       {
+                               if (filter == null || filter(member, filterCriteria))
+                               {
+                                       list.Add(member);
+                               }
+                       }
+               }
+
+               public MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria)
+               {
+                       List<MemberInfo> members = new List<MemberInfo>();
+                       if ((memberType & MemberTypes.Constructor) != 0)
+                       {
+                               AddMembers(members, filter, filterCriteria, GetConstructors(bindingAttr));
+                       }
+                       if ((memberType & MemberTypes.Method) != 0)
+                       {
+                               AddMembers(members, filter, filterCriteria, GetMethods(bindingAttr));
+                       }
+                       if ((memberType & MemberTypes.Field) != 0)
+                       {
+                               AddMembers(members, filter, filterCriteria, GetFields(bindingAttr));
+                       }
+                       if ((memberType & MemberTypes.Property) != 0)
+                       {
+                               AddMembers(members, filter, filterCriteria, GetProperties(bindingAttr));
+                       }
+                       if ((memberType & MemberTypes.Event) != 0)
+                       {
+                               AddMembers(members, filter, filterCriteria, GetEvents(bindingAttr));
+                       }
+                       if ((memberType & MemberTypes.NestedType) != 0)
+                       {
+                               AddMembers(members, filter, filterCriteria, GetNestedTypes(bindingAttr));
+                       }
+                       return members.ToArray();
+               }
+
+               public EventInfo GetEvent(string name)
+               {
+                       return GetEvent(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public EventInfo GetEvent(string name, BindingFlags bindingAttr)
+               {
+                       foreach (EventInfo evt in GetEvents(bindingAttr))
+                       {
+                               if (evt.Name == name)
+                               {
+                                       return evt;
+                               }
+                       }
+                       return null;
+               }
+
+               public EventInfo[] GetEvents()
+               {
+                       return GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public EventInfo[] GetEvents(BindingFlags bindingAttr)
+               {
+                       List<EventInfo> list = new List<EventInfo>();
+                       Type type = this;
+                       while (type != null)
+                       {
+                               type.CheckBaked();
+                               foreach (EventInfo evt in type.__GetDeclaredEvents())
+                               {
+                                       if (BindingFlagsMatch(evt.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+                                               && BindingFlagsMatch(evt.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                                       {
+                                               list.Add(evt);
+                                       }
+                               }
+                               if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+                               {
+                                       if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
+                                       {
+                                               bindingAttr &= ~BindingFlags.Static;
+                                       }
+                                       type = type.BaseType;
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public FieldInfo GetField(string name)
+               {
+                       return GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public FieldInfo GetField(string name, BindingFlags bindingAttr)
+               {
+                       foreach (FieldInfo field in GetFields(bindingAttr))
+                       {
+                               if (field.Name == name)
+                               {
+                                       return field;
+                               }
+                       }
+                       return null;
+               }
+
+               public FieldInfo[] GetFields()
+               {
+                       return GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
+               }
+
+               public FieldInfo[] GetFields(BindingFlags bindingAttr)
+               {
+                       List<FieldInfo> list = new List<FieldInfo>();
+                       CheckBaked();
+                       foreach (FieldInfo field in __GetDeclaredFields())
+                       {
+                               if (BindingFlagsMatch(field.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+                                       && BindingFlagsMatch(field.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                               {
+                                       list.Add(field);
+                               }
+                       }
+                       if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+                       {
+                               for (Type type = this.BaseType; type != null; type = type.BaseType)
+                               {
+                                       type.CheckBaked();
+                                       foreach (FieldInfo field in type.__GetDeclaredFields())
+                                       {
+                                               if ((field.Attributes & FieldAttributes.FieldAccessMask) > FieldAttributes.Private
+                                                       && BindingFlagsMatch(field.IsStatic, bindingAttr, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance))
+                                               {
+                                                       list.Add(field);
+                                               }
+                                       }
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public Type[] GetInterfaces()
+               {
+                       List<Type> list = new List<Type>();
+                       for (Type type = this; type != null; type = type.BaseType)
+                       {
+                               AddInterfaces(list, type);
+                       }
+                       return list.ToArray();
+               }
+
+               private static void AddInterfaces(List<Type> list, Type type)
+               {
+                       type.CheckBaked();
+                       foreach (Type iface in type.__GetDeclaredInterfaces())
+                       {
+                               if (!list.Contains(iface))
+                               {
+                                       list.Add(iface);
+                                       AddInterfaces(list, iface);
+                               }
+                       }
+               }
+
+               public MethodInfo[] GetMethods(BindingFlags bindingAttr)
+               {
+                       CheckBaked();
+                       List<MethodInfo> list = new List<MethodInfo>();
+                       foreach (MethodBase mb in __GetDeclaredMethods())
+                       {
+                               MethodInfo mi = mb as MethodInfo;
+                               if (mi != null
+                                       && BindingFlagsMatch(mi.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+                                       && BindingFlagsMatch(mi.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                               {
+                                       list.Add(mi);
+                               }
+                       }
+                       if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+                       {
+                               for (Type type = this.BaseType; type != null; type = type.BaseType)
+                               {
+                                       type.CheckBaked();
+                                       foreach (MethodBase mb in type.__GetDeclaredMethods())
+                                       {
+                                               MethodInfo mi = mb as MethodInfo;
+                                               if (mi != null
+                                                       && (mi.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private
+                                                       && BindingFlagsMatch(mi.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+                                                       && BindingFlagsMatch(mi.IsStatic, bindingAttr, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance)
+                                                       && !FindMethod(list, mi))
+                                               {
+                                                       list.Add(mi);
+                                               }
+                                       }
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               private static bool FindMethod(List<MethodInfo> methods, MethodInfo method)
+               {
+                       foreach (MethodInfo m in methods)
+                       {
+                               if (m.Name == method.Name && m.MethodSignature.Equals(method.MethodSignature))
+                               {
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
+               public MethodInfo[] GetMethods()
+               {
+                       return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
+               }
+
+               public MethodInfo GetMethod(string name)
+               {
+                       return GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+               }
+
+               public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
+               {
+                       MethodInfo found = null;
+                       foreach (MethodInfo method in GetMethods(bindingAttr))
+                       {
+                               if (method.Name == name)
+                               {
+                                       if (found != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       found = method;
+                               }
+                       }
+                       return found;
+               }
+
+               public MethodInfo GetMethod(string name, Type[] types)
+               {
+                       return GetMethod(name, types, null);
+               }
+
+               public MethodInfo GetMethod(string name, Type[] types, ParameterModifier[] modifiers)
+               {
+                       return GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, types, modifiers);
+               }
+
+               public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+               {
+                       MethodInfo found = null;
+                       foreach (MethodInfo method in GetMethods(bindingAttr))
+                       {
+                               if (method.Name == name && method.MethodSignature.MatchParameterTypes(types))
+                               {
+                                       if (found != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       found = method;
+                               }
+                       }
+                       return found;
+               }
+
+               public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+               {
+                       // FXBUG callConvention seems to be ignored
+                       return GetMethod(name, bindingAttr, binder, types, modifiers);
+               }
+
+               public ConstructorInfo[] GetConstructors()
+               {
+                       return GetConstructors(BindingFlags.Public | BindingFlags.Instance);
+               }
+
+               public ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+               {
+                       CheckBaked();
+                       List<ConstructorInfo> list = new List<ConstructorInfo>();
+                       foreach (MethodBase mb in __GetDeclaredMethods())
+                       {
+                               ConstructorInfo constructor = mb as ConstructorInfo;
+                               if (constructor != null
+                                       && BindingFlagsMatch(constructor.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+                                       && BindingFlagsMatch(constructor.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                               {
+                                       list.Add(constructor);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public ConstructorInfo GetConstructor(Type[] types)
+               {
+                       return GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Standard, types, null);
+               }
+
+               public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+               {
+                       foreach (ConstructorInfo constructor in GetConstructors(bindingAttr))
+                       {
+                               if (constructor.MethodSignature.MatchParameterTypes(types))
+                               {
+                                       return constructor;
+                               }
+                       }
+                       return null;
+               }
+
+               public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callingConvention, Type[] types, ParameterModifier[] modifiers)
+               {
+                       // FXBUG callConvention seems to be ignored
+                       return GetConstructor(bindingAttr, binder, types, modifiers);
+               }
+
+               public Type GetNestedType(string name)
+               {
+                       return GetNestedType(name, BindingFlags.Public);
+               }
+
+               public Type GetNestedType(string name, BindingFlags bindingAttr)
+               {
+                       foreach (Type type in GetNestedTypes(bindingAttr))
+                       {
+                               if (type.Name == name)
+                               {
+                                       return type;
+                               }
+                       }
+                       return null;
+               }
+
+               public Type[] GetNestedTypes()
+               {
+                       return GetNestedTypes(BindingFlags.Public);
+               }
+
+               public Type[] GetNestedTypes(BindingFlags bindingAttr)
+               {
+                       CheckBaked();
+                       List<Type> list = new List<Type>();
+                       foreach (Type type in __GetDeclaredTypes())
+                       {
+                               if (BindingFlagsMatch(type.IsNestedPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic))
+                               {
+                                       list.Add(type);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public PropertyInfo[] GetProperties()
+               {
+                       return GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+               {
+                       List<PropertyInfo> list = new List<PropertyInfo>();
+                       Type type = this;
+                       while (type != null)
+                       {
+                               type.CheckBaked();
+                               foreach (PropertyInfo property in type.__GetDeclaredProperties())
+                               {
+                                       if (BindingFlagsMatch(property.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+                                               && BindingFlagsMatch(property.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                                       {
+                                               list.Add(property);
+                                       }
+                               }
+                               if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+                               {
+                                       if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
+                                       {
+                                               bindingAttr &= ~BindingFlags.Static;
+                                       }
+                                       type = type.BaseType;
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public PropertyInfo GetProperty(string name)
+               {
+                       return GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
+               {
+                       foreach (PropertyInfo prop in GetProperties(bindingAttr))
+                       {
+                               if (prop.Name == name)
+                               {
+                                       return prop;
+                               }
+                       }
+                       return null;
+               }
+
+               public PropertyInfo GetProperty(string name, Type returnType)
+               {
+                       PropertyInfo found = null;
+                       foreach (PropertyInfo prop in GetProperties())
+                       {
+                               if (prop.Name == name && prop.PropertyType.Equals(returnType))
+                               {
+                                       if (found != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       found = prop;
+                               }
+                       }
+                       return found;
+               }
+
+               public PropertyInfo GetProperty(string name, Type[] types)
+               {
+                       PropertyInfo found = null;
+                       foreach (PropertyInfo prop in GetProperties())
+                       {
+                               if (prop.Name == name && MatchParameterTypes(prop.GetIndexParameters(), types))
+                               {
+                                       if (found != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       found = prop;
+                               }
+                       }
+                       return found;
+               }
+
+               private static bool MatchParameterTypes(ParameterInfo[] parameters, Type[] types)
+               {
+                       if (parameters.Length == types.Length)
+                       {
+                               for (int i = 0; i < parameters.Length; i++)
+                               {
+                                       if (!parameters[i].ParameterType.Equals(types[i]))
+                                       {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               public PropertyInfo GetProperty(string name, Type returnType, Type[] types)
+               {
+                       return GetProperty(name, returnType, types, null);
+               }
+
+               public PropertyInfo GetProperty(string name, Type returnType, Type[] types, ParameterModifier[] modifiers)
+               {
+                       return GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, returnType, types, modifiers);
+               }
+
+               public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+               {
+                       PropertyInfo found = null;
+                       foreach (PropertyInfo prop in GetProperties(bindingAttr))
+                       {
+                               if (prop.Name == name && prop.PropertyType.Equals(returnType) && MatchParameterTypes(prop.GetIndexParameters(), types))
+                               {
+                                       if (found != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       found = prop;
+                               }
+                       }
+                       return found;
+               }
+
+               public Type GetInterface(string name)
+               {
+                       return GetInterface(name, false);
+               }
+
+               public Type GetInterface(string name, bool ignoreCase)
+               {
+                       if (ignoreCase)
+                       {
+                               throw new NotImplementedException();
+                       }
+                       foreach (Type type in GetInterfaces())
+                       {
+                               if (type.FullName == name)
+                               {
+                                       return type;
+                               }
+                       }
+                       return null;
+               }
+
+               public Type[] FindInterfaces(TypeFilter filter, object filterCriteria)
+               {
+                       List<Type> list = new List<Type>();
+                       foreach (Type type in GetInterfaces())
+                       {
+                               if (filter(type, filterCriteria))
+                               {
+                                       list.Add(type);
+                               }
+                       }
+                       return list.ToArray();
+               }
+
+               public ConstructorInfo TypeInitializer
+               {
+                       get { return GetConstructor(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); }
+               }
+
+               public bool IsPrimitive
+               {
+                       get
+                       {
+                               Universe u = this.Module.universe;
+                               return this == u.System_Boolean
+                                       || this == u.System_Byte
+                                       || this == u.System_SByte
+                                       || this == u.System_Int16
+                                       || this == u.System_UInt16
+                                       || this == u.System_Int32
+                                       || this == u.System_UInt32
+                                       || this == u.System_Int64
+                                       || this == u.System_UInt64
+                                       || this == u.System_IntPtr
+                                       || this == u.System_UIntPtr
+                                       || this == u.System_Char
+                                       || this == u.System_Double
+                                       || this == u.System_Single
+                                       ;
+                       }
+               }
+
+               public bool IsEnum
+               {
+                       get { return this.BaseType == this.Module.universe.System_Enum; }
+               }
+
+               public bool IsSealed
+               {
+                       get { return (Attributes & TypeAttributes.Sealed) != 0; }
+               }
+
+               public bool IsAbstract
+               {
+                       get { return (Attributes & TypeAttributes.Abstract) != 0; }
+               }
+
+               private bool CheckVisibility(TypeAttributes access)
+               {
+                       return (Attributes & TypeAttributes.VisibilityMask) == access;
+               }
+
+               public bool IsPublic
+               {
+                       get { return CheckVisibility(TypeAttributes.Public); }
+               }
+
+               public bool IsNestedPublic
+               {
+                       get { return CheckVisibility(TypeAttributes.NestedPublic); }
+               }
+
+               public bool IsNestedPrivate
+               {
+                       get { return CheckVisibility(TypeAttributes.NestedPrivate); }
+               }
+
+               public bool IsNestedFamily
+               {
+                       get { return CheckVisibility(TypeAttributes.NestedFamily); }
+               }
+
+               public bool IsNestedAssembly
+               {
+                       get { return CheckVisibility(TypeAttributes.NestedAssembly); }
+               }
+
+               public bool IsNestedFamANDAssem
+               {
+                       get { return CheckVisibility(TypeAttributes.NestedFamANDAssem); }
+               }
+
+               public bool IsNestedFamORAssem
+               {
+                       get { return CheckVisibility(TypeAttributes.NestedFamORAssem); }
+               }
+
+               public bool IsNotPublic
+               {
+                       get { return CheckVisibility(TypeAttributes.NotPublic); }
+               }
+
+               public bool IsImport
+               {
+                       get { return (Attributes & TypeAttributes.Import) != 0; }
+               }
+
+               public bool IsCOMObject
+               {
+                       get { return IsClass && IsImport; }
+               }
+
+               public bool IsContextful
+               {
+                       get { return IsSubclassOf(this.Module.universe.Import(typeof(ContextBoundObject))); }
+               }
+
+               public bool IsMarshalByRef
+               {
+                       get { return IsSubclassOf(this.Module.universe.Import(typeof(MarshalByRefObject))); }
+               }
+
+               public virtual bool IsVisible
+               {
+                       get { return IsPublic || (IsNestedPublic && this.DeclaringType.IsVisible); }
+               }
+
+               public bool IsAnsiClass
+               {
+                       get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass; }
+               }
+
+               public bool IsUnicodeClass
+               {
+                       get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass; }
+               }
+
+               public bool IsAutoClass
+               {
+                       get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass; }
+               }
+
+               public bool IsAutoLayout
+               {
+                       get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout; }
+               }
+
+               public bool IsLayoutSequential
+               {
+                       get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout; }
+               }
+
+               public bool IsExplicitLayout
+               {
+                       get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout; }
+               }
+
+               public bool IsSpecialName
+               {
+                       get { return (Attributes & TypeAttributes.SpecialName) != 0; }
+               }
+
+               public bool IsSerializable
+               {
+                       get { return (Attributes & TypeAttributes.Serializable) != 0; }
+               }
+
+               public bool IsClass
+               {
+                       get { return !IsInterface && !IsValueType; }
+               }
+
+               public bool IsInterface
+               {
+                       get { return (Attributes & TypeAttributes.Interface) != 0; }
+               }
+
+               public bool IsNested
+               {
+                       // FXBUG we check the declaring type (like .NET) and this results
+                       // in IsNested returning true for a generic type parameter
+                       get { return this.DeclaringType != null; }
+               }
+
+               public Type MakeArrayType()
+               {
+                       return ArrayType.Make(this, null, null);
+               }
+
+               public Type __MakeArrayType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return ArrayType.Make(this, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+               }
+
+               public Type MakeArrayType(int rank)
+               {
+                       return MultiArrayType.Make(this, rank, null, null);
+               }
+
+               public Type __MakeArrayType(int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return MultiArrayType.Make(this, rank, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+               }
+
+               public Type MakeByRefType()
+               {
+                       return ByRefType.Make(this, null, null);
+               }
+
+               public Type __MakeByRefType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return ByRefType.Make(this, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+               }
+
+               public Type MakePointerType()
+               {
+                       return PointerType.Make(this, null, null);
+               }
+
+               public Type __MakePointerType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return PointerType.Make(this, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+               }
+
+               public Type MakeGenericType(params Type[] typeArguments)
+               {
+                       return __MakeGenericType(typeArguments, null, null);
+               }
+
+               public Type __MakeGenericType(Type[] typeArguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+               {
+                       if (!this.IsGenericTypeDefinition)
+                       {
+                               throw new InvalidOperationException();
+                       }
+                       return GenericTypeInstance.Make(this, Util.Copy(typeArguments), Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+               }
+
+               public static System.Type __GetSystemType(TypeCode typeCode)
+               {
+                       switch (typeCode)
+                       {
+                               case TypeCode.Boolean:
+                                       return typeof(System.Boolean);
+                               case TypeCode.Byte:
+                                       return typeof(System.Byte);
+                               case TypeCode.Char:
+                                       return typeof(System.Char);
+                               case TypeCode.DBNull:
+                                       return typeof(System.DBNull);
+                               case TypeCode.DateTime:
+                                       return typeof(System.DateTime);
+                               case TypeCode.Decimal:
+                                       return typeof(System.Decimal);
+                               case TypeCode.Double:
+                                       return typeof(System.Double);
+                               case TypeCode.Empty:
+                                       return null;
+                               case TypeCode.Int16:
+                                       return typeof(System.Int16);
+                               case TypeCode.Int32:
+                                       return typeof(System.Int32);
+                               case TypeCode.Int64:
+                                       return typeof(System.Int64);
+                               case TypeCode.Object:
+                                       return typeof(System.Object);
+                               case TypeCode.SByte:
+                                       return typeof(System.SByte);
+                               case TypeCode.Single:
+                                       return typeof(System.Single);
+                               case TypeCode.String:
+                                       return typeof(System.String);
+                               case TypeCode.UInt16:
+                                       return typeof(System.UInt16);
+                               case TypeCode.UInt32:
+                                       return typeof(System.UInt32);
+                               case TypeCode.UInt64:
+                                       return typeof(System.UInt64);
+                               default:
+                                       throw new ArgumentOutOfRangeException();
+                       }
+               }
+
+               public static TypeCode GetTypeCode(Type type)
+               {
+                       if (type == null)
+                       {
+                               return TypeCode.Empty;
+                       }
+                       if (type.IsEnum)
+                       {
+                               type = type.GetEnumUnderlyingType();
+                       }
+                       Universe u = type.Module.universe;
+                       if (type == u.System_Boolean)
+                       {
+                               return TypeCode.Boolean;
+                       }
+                       else if (type == u.System_Char)
+                       {
+                               return TypeCode.Char;
+                       }
+                       else if (type == u.System_SByte)
+                       {
+                               return TypeCode.SByte;
+                       }
+                       else if (type == u.System_Byte)
+                       {
+                               return TypeCode.Byte;
+                       }
+                       else if (type == u.System_Int16)
+                       {
+                               return TypeCode.Int16;
+                       }
+                       else if (type == u.System_UInt16)
+                       {
+                               return TypeCode.UInt16;
+                       }
+                       else if (type == u.System_Int32)
+                       {
+                               return TypeCode.Int32;
+                       }
+                       else if (type == u.System_UInt32)
+                       {
+                               return TypeCode.UInt32;
+                       }
+                       else if (type == u.System_Int64)
+                       {
+                               return TypeCode.Int64;
+                       }
+                       else if (type == u.System_UInt64)
+                       {
+                               return TypeCode.UInt64;
+                       }
+                       else if (type == u.System_Single)
+                       {
+                               return TypeCode.Single;
+                       }
+                       else if (type == u.System_Double)
+                       {
+                               return TypeCode.Double;
+                       }
+                       else if (type == u.System_DateTime)
+                       {
+                               return TypeCode.DateTime;
+                       }
+                       else if (type == u.System_DBNull)
+                       {
+                               return TypeCode.DBNull;
+                       }
+                       else if (type == u.System_Decimal)
+                       {
+                               return TypeCode.Decimal;
+                       }
+                       else if (type == u.System_String)
+                       {
+                               return TypeCode.String;
+                       }
+                       else
+                       {
+                               return TypeCode.Object;
+                       }
+               }
+
+               public Assembly Assembly
+               {
+                       get { return Module.Assembly; }
+               }
+
+               // note that interface/delegate co- and contravariance is not considered
+               public bool IsAssignableFrom(Type type)
+               {
+                       if (this.Equals(type))
+                       {
+                               return true;
+                       }
+                       else if (type == null)
+                       {
+                               return false;
+                       }
+                       else if (this.IsArray && type.IsArray)
+                       {
+                               if (this.GetArrayRank() != type.GetArrayRank())
+                               {
+                                       return false;
+                               }
+                               else if (this.__IsVector && !type.__IsVector)
+                               {
+                                       return false;
+                               }
+                               Type e1 = this.GetElementType();
+                               Type e2 = type.GetElementType();
+                               return e1.IsValueType == e2.IsValueType && e1.IsAssignableFrom(e2);
+                       }
+                       else if (this.IsSealed)
+                       {
+                               return false;
+                       }
+                       else if (this.IsInterface)
+                       {
+                               return Array.IndexOf(type.GetInterfaces(), this) != -1;
+                       }
+                       else if (type.IsInterface)
+                       {
+                               return this == this.Module.universe.System_Object;
+                       }
+                       else if (type.IsPointer)
+                       {
+                               return this == this.Module.universe.System_Object || this == this.Module.universe.System_ValueType;
+                       }
+                       else
+                       {
+                               return type.IsSubclassOf(this);
+                       }
+               }
+
+               public bool IsSubclassOf(Type type)
+               {
+                       Type thisType = this.BaseType;
+                       while (thisType != null)
+                       {
+                               if (thisType.Equals(type))
+                               {
+                                       return true;
+                               }
+                               thisType = thisType.BaseType;
+                       }
+                       return false;
+               }
+
+               // This returns true if this type directly (i.e. not inherited from the base class) implements the interface.
+               // Note that a complicating factor is that the interface itself can be implemented by an interface that extends it.
+               private bool IsDirectlyImplementedInterface(Type interfaceType)
+               {
+                       foreach (Type iface in __GetDeclaredInterfaces())
+                       {
+                               if (interfaceType.IsAssignableFrom(iface))
+                               {
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
+               public InterfaceMapping GetInterfaceMap(Type interfaceType)
+               {
+                       CheckBaked();
+                       InterfaceMapping map = new InterfaceMapping();
+                       if (!IsDirectlyImplementedInterface(interfaceType))
+                       {
+                               Type baseType = this.BaseType;
+                               if (baseType == null)
+                               {
+                                       throw new ArgumentException();
+                               }
+                               else
+                               {
+                                       map = baseType.GetInterfaceMap(interfaceType);
+                               }
+                       }
+                       else
+                       {
+                               map.InterfaceMethods = interfaceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
+                               map.InterfaceType = interfaceType;
+                               map.TargetMethods = new MethodInfo[map.InterfaceMethods.Length];
+                               FillInExplicitInterfaceMethods(map.InterfaceMethods, map.TargetMethods);
+                               MethodInfo[] methods = GetMethods(BindingFlags.Instance | BindingFlags.Public);
+                               for (int i = 0; i < map.TargetMethods.Length; i++)
+                               {
+                                       if (map.TargetMethods[i] == null)
+                                       {
+                                               // TODO use proper method resolution (also take into account that no implicit base class implementation is used across assembly boundaries)
+                                               for (int j = 0; j < methods.Length; j++)
+                                               {
+                                                       if (methods[j].Name == map.InterfaceMethods[i].Name
+                                                               && methods[j].MethodSignature.Equals(map.InterfaceMethods[i].MethodSignature))
+                                                       {
+                                                               map.TargetMethods[i] = methods[j];
+                                                       }
+                                               }
+                                       }
+                               }
+                               for (Type baseType = this.BaseType; baseType != null && interfaceType.IsAssignableFrom(baseType); baseType = baseType.BaseType)
+                               {
+                                       baseType.FillInExplicitInterfaceMethods(map.InterfaceMethods, map.TargetMethods);
+                               }
+                       }
+                       map.TargetType = this;
+                       return map;
+               }
+
+               internal void FillInExplicitInterfaceMethods(MethodInfo[] interfaceMethods, MethodInfo[] targetMethods)
+               {
+                       __MethodImplMap impl = __GetMethodImplMap();
+                       for (int i = 0; i < impl.MethodDeclarations.Length; i++)
+                       {
+                               for (int j = 0; j < impl.MethodDeclarations[i].Length; j++)
+                               {
+                                       int index = Array.IndexOf(interfaceMethods, impl.MethodDeclarations[i][j]);
+                                       if (index != -1 && targetMethods[index] == null)
+                                       {
+                                               targetMethods[index] = impl.MethodBodies[i];
+                                       }
+                               }
+                       }
+               }
+
+               Type IGenericContext.GetGenericTypeArgument(int index)
+               {
+                       return GetGenericTypeArgument(index);
+               }
+
+               Type IGenericContext.GetGenericMethodArgument(int index)
+               {
+                       throw new BadImageFormatException();
+               }
+
+               Type IGenericBinder.BindTypeParameter(Type type)
+               {
+                       return GetGenericTypeArgument(type.GenericParameterPosition);
+               }
+
+               Type IGenericBinder.BindMethodParameter(Type type)
+               {
+                       throw new BadImageFormatException();
+               }
+
+               internal virtual Type BindTypeParameters(IGenericBinder binder)
+               {
+                       if (IsGenericTypeDefinition)
+                       {
+                               Type[] args = GetGenericArguments();
+                               Type.InplaceBindTypeParameters(binder, args);
+                               return GenericTypeInstance.Make(this, args, null, null);
+                       }
+                       else
+                       {
+                               return this;
+                       }
+               }
+
+               internal static void InplaceBindTypeParameters(IGenericBinder binder, Type[] types)
+               {
+                       for (int i = 0; i < types.Length; i++)
+                       {
+                               types[i] = types[i].BindTypeParameters(binder);
+                       }
+               }
+
+               internal MethodBase FindMethod(string name, MethodSignature signature)
+               {
+                       foreach (MethodBase method in __GetDeclaredMethods())
+                       {
+                               if (method.Name == name && method.MethodSignature.Equals(signature))
+                               {
+                                       return method;
+                               }
+                       }
+                       return null;
+               }
+
+               internal FieldInfo FindField(string name, FieldSignature signature)
+               {
+                       foreach (FieldInfo field in __GetDeclaredFields())
+                       {
+                               if (field.Name == name && field.FieldSignature.Equals(signature))
+                               {
+                                       return field;
+                               }
+                       }
+                       return null;
+               }
+
+               internal bool IsAllowMultipleCustomAttribute
+               {
+                       get
+                       {
+                               IList<CustomAttributeData> cad = GetCustomAttributesData(this.Module.universe.System_AttributeUsageAttribute);
+                               if (cad.Count == 1)
+                               {
+                                       foreach (CustomAttributeNamedArgument arg in cad[0].NamedArguments)
+                                       {
+                                               if (arg.MemberInfo.Name == "AllowMultiple")
+                                               {
+                                                       return (bool)arg.TypedValue.Value;
+                                               }
+                                       }
+                               }
+                               return false;
+                       }
+               }
+
+               internal bool IsPseudoCustomAttribute
+               {
+                       get
+                       {
+                               Universe u = this.Module.universe;
+                               return this == u.System_NonSerializedAttribute
+                                       || this == u.System_SerializableAttribute
+                                       || this == u.System_Runtime_InteropServices_DllImportAttribute
+                                       || this == u.System_Runtime_InteropServices_FieldOffsetAttribute
+                                       || this == u.System_Runtime_InteropServices_InAttribute
+                                       || this == u.System_Runtime_InteropServices_MarshalAsAttribute
+                                       || this == u.System_Runtime_InteropServices_OutAttribute
+                                       || this == u.System_Runtime_InteropServices_StructLayoutAttribute
+                                       || this == u.System_Runtime_InteropServices_OptionalAttribute
+                                       || this == u.System_Runtime_InteropServices_PreserveSigAttribute
+                                       || this == u.System_Runtime_InteropServices_ComImportAttribute
+                                       || this == u.System_Runtime_CompilerServices_SpecialNameAttribute
+                                       || this == u.System_Runtime_CompilerServices_MethodImplAttribute
+                                       ;
+                       }
+               }
+       }
+
+       abstract class ElementHolderType : Type
+       {
+               protected readonly Type elementType;
+               private int token;
+               private readonly Type[] requiredCustomModifiers;
+               private readonly Type[] optionalCustomModifiers;
+
+               protected ElementHolderType(Type elementType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       this.elementType = elementType;
+                       this.requiredCustomModifiers = requiredCustomModifiers;
+                       this.optionalCustomModifiers = optionalCustomModifiers;
+               }
+
+               protected bool EqualsHelper(ElementHolderType other)
+               {
+                       return other != null
+                               && other.elementType.Equals(elementType)
+                               && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers)
+                               && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers);
+               }
+
+               public override Type[] __GetRequiredCustomModifiers()
+               {
+                       return Util.Copy(requiredCustomModifiers);
+               }
+
+               public override Type[] __GetOptionalCustomModifiers()
+               {
+                       return Util.Copy(optionalCustomModifiers);
+               }
+
+               public sealed override string Name
+               {
+                       get { return elementType.Name + GetSuffix(); }
+               }
+
+               public sealed override string FullName
+               {
+                       get { return elementType.FullName + GetSuffix(); }
+               }
+
+               public sealed override string ToString()
+               {
+                       return elementType.ToString() + GetSuffix();
+               }
+
+               public sealed override Type GetElementType()
+               {
+                       return elementType;
+               }
+
+               public sealed override bool HasElementType
+               {
+                       get { return true; }
+               }
+
+               public sealed override Module Module
+               {
+                       get { return elementType.Module; }
+               }
+
+               internal sealed override int GetModuleBuilderToken()
+               {
+                       if (token == 0)
+                       {
+                               token = ((ModuleBuilder)elementType.Module).ImportType(this);
+                       }
+                       return token;
+               }
+
+               public sealed override bool ContainsGenericParameters
+               {
+                       get
+                       {
+                               Type type = elementType;
+                               while (type.HasElementType)
+                               {
+                                       type = type.GetElementType();
+                               }
+                               return type.ContainsGenericParameters;
+                       }
+               }
+
+               internal sealed override Type BindTypeParameters(IGenericBinder binder)
+               {
+                       Type type = elementType.BindTypeParameters(binder);
+                       Type[] req = BindArray(requiredCustomModifiers, binder);
+                       Type[] opt = BindArray(optionalCustomModifiers, binder);
+                       if (ReferenceEquals(type, elementType)
+                               && ReferenceEquals(req, requiredCustomModifiers)
+                               && ReferenceEquals(opt, optionalCustomModifiers))
+                       {
+                               return this;
+                       }
+                       return Wrap(type, req, opt);
+               }
+
+               internal override void CheckBaked()
+               {
+                       elementType.CheckBaked();
+               }
+
+               private static Type[] BindArray(Type[] array, IGenericBinder binder)
+               {
+                       if (array ==null || array.Length == 0)
+                       {
+                               return array;
+                       }
+                       Type[] result = array;
+                       for (int i = 0; i < array.Length; i++)
+                       {
+                               Type type = array[i].BindTypeParameters(binder);
+                               if (!ReferenceEquals(type, array[i]))
+                               {
+                                       if (result == array)
+                                       {
+                                               result = (Type[])array.Clone();
+                                       }
+                                       result[i] = type;
+                               }
+                       }
+                       return result;
+               }
+
+               internal sealed override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return CustomAttributeData.EmptyList;
+               }
+
+               protected abstract string GetSuffix();
+
+               protected abstract Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers);
+       }
+
+       sealed class ArrayType : ElementHolderType
+       {
+               internal static Type Make(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return type.Module.CanonicalizeType(new ArrayType(type, requiredCustomModifiers, optionalCustomModifiers));
+               }
+
+               private ArrayType(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+                       : base(type, requiredCustomModifiers, optionalCustomModifiers)
+               {
+               }
+
+               public override Type BaseType
+               {
+                       get { return elementType.Module.universe.System_Array; }
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       return new Type[] {
+                               this.Module.universe.Import(typeof(IList<>)).MakeGenericType(elementType),
+                               this.Module.universe.Import(typeof(ICollection<>)).MakeGenericType(elementType),
+                               this.Module.universe.Import(typeof(IEnumerable<>)).MakeGenericType(elementType)
+                       };
+               }
+
+               public override MethodBase[] __GetDeclaredMethods()
+               {
+                       Type[] int32 = new Type[] { this.Module.universe.System_Int32 };
+                       List<MethodBase> list = new List<MethodBase>();
+                       list.Add(new BuiltinArrayMethod(this.Module, this, "Set", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, new Type[] { this.Module.universe.System_Int32, elementType }));
+                       list.Add(new BuiltinArrayMethod(this.Module, this, "Address", CallingConventions.Standard | CallingConventions.HasThis, elementType.MakeByRefType(), int32));
+                       list.Add(new BuiltinArrayMethod(this.Module, this, "Get", CallingConventions.Standard | CallingConventions.HasThis, elementType, int32));
+                       list.Add(new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, int32)));
+                       for (Type type = elementType; type.__IsVector; type = type.GetElementType())
+                       {
+                               Array.Resize(ref int32, int32.Length + 1);
+                               int32[int32.Length - 1] = int32[0];
+                               list.Add(new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, int32)));
+                       }
+                       return list.ToArray();
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; }
+               }
+
+               public override bool IsArray
+               {
+                       get { return true; }
+               }
+
+               public override bool __IsVector
+               {
+                       get { return true; }
+               }
+
+               public override int GetArrayRank()
+               {
+                       return 1;
+               }
+
+               public override bool Equals(object o)
+               {
+                       return EqualsHelper(o as ArrayType);
+               }
+
+               public override int GetHashCode()
+               {
+                       return elementType.GetHashCode() * 5;
+               }
+
+               protected override string GetSuffix()
+               {
+                       return "[]";
+               }
+
+               protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return Make(type, requiredCustomModifiers, optionalCustomModifiers);
+               }
+       }
+
+       sealed class MultiArrayType : ElementHolderType
+       {
+               private readonly int rank;
+
+               internal static Type Make(Type type, int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return type.Module.CanonicalizeType(new MultiArrayType(type, rank, requiredCustomModifiers, optionalCustomModifiers));
+               }
+
+               private MultiArrayType(Type type, int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+                       : base(type, requiredCustomModifiers, optionalCustomModifiers)
+               {
+                       this.rank = rank;
+               }
+
+               public override Type BaseType
+               {
+                       get { return elementType.Module.universe.System_Array; }
+               }
+
+               public override MethodBase[] __GetDeclaredMethods()
+               {
+                       Type int32 = this.Module.universe.System_Int32;
+                       Type[] setArgs = new Type[rank + 1];
+                       Type[] getArgs = new Type[rank];
+                       Type[] ctorArgs = new Type[rank * 2];
+                       for (int i = 0; i < rank; i++)
+                       {
+                               setArgs[i] = int32;
+                               getArgs[i] = int32;
+                               ctorArgs[i * 2 + 0] = int32;
+                               ctorArgs[i * 2 + 1] = int32;
+                       }
+                       setArgs[rank] = elementType;
+                       return new MethodBase[] {
+                               new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, getArgs)),
+                               new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, ctorArgs)),
+                               new BuiltinArrayMethod(this.Module, this, "Set", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, setArgs),
+                               new BuiltinArrayMethod(this.Module, this, "Address", CallingConventions.Standard | CallingConventions.HasThis, elementType.MakeByRefType(), getArgs),
+                               new BuiltinArrayMethod(this.Module, this, "Get", CallingConventions.Standard | CallingConventions.HasThis, elementType, getArgs),
+                       };
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; }
+               }
+
+               public override bool IsArray
+               {
+                       get { return true; }
+               }
+
+               public override int GetArrayRank()
+               {
+                       return rank;
+               }
+
+               public override bool Equals(object o)
+               {
+                       MultiArrayType at = o as MultiArrayType;
+                       return EqualsHelper(at) && at.rank == rank;
+               }
+
+               public override int GetHashCode()
+               {
+                       return elementType.GetHashCode() * 9 + rank;
+               }
+
+               protected override string GetSuffix()
+               {
+                       if (rank == 1)
+                       {
+                               return "[*]";
+                       }
+                       else
+                       {
+                               return "[" + new String(',', rank - 1) + "]";
+                       }
+               }
+
+               protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return Make(type, rank, requiredCustomModifiers, optionalCustomModifiers);
+               }
+       }
+
+       sealed class BuiltinArrayMethod : ArrayMethod
+       {
+               internal BuiltinArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+                       : base(module, arrayClass, methodName, callingConvention, returnType, parameterTypes)
+               {
+               }
+
+               public override MethodAttributes Attributes
+               {
+                       get { return this.Name == ".ctor" ? MethodAttributes.RTSpecialName | MethodAttributes.Public : MethodAttributes.Public; }
+               }
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
+                       return MethodImplAttributes.IL;
+               }
+
+               public override int MetadataToken
+               {
+                       get { return 0x06000000; }
+               }
+
+               public override MethodBody GetMethodBody()
+               {
+                       return null;
+               }
+
+               public override ParameterInfo[] GetParameters()
+               {
+                       ParameterInfo[] parameterInfos = new ParameterInfo[parameterTypes.Length];
+                       for (int i = 0; i < parameterInfos.Length; i++)
+                       {
+                               parameterInfos[i] = new ParameterInfoImpl(this, parameterTypes[i], i);
+                       }
+                       return parameterInfos;
+               }
+
+               public override ParameterInfo ReturnParameter
+               {
+                       get { return new ParameterInfoImpl(this, this.ReturnType, -1); }
+               }
+
+               private sealed class ParameterInfoImpl : ParameterInfo
+               {
+                       private readonly MethodInfo method;
+                       private readonly Type type;
+                       private readonly int pos;
+
+                       internal ParameterInfoImpl(MethodInfo method, Type type, int pos)
+                       {
+                               this.method = method;
+                               this.type = type;
+                               this.pos = pos;
+                       }
+
+                       public override Type ParameterType
+                       {
+                               get { return type; }
+                       }
+
+                       public override string Name
+                       {
+                               get { return null; }
+                       }
+
+                       public override ParameterAttributes Attributes
+                       {
+                               get { return ParameterAttributes.None; }
+                       }
+
+                       public override int Position
+                       {
+                               get { return pos; }
+                       }
+
+                       public override object RawDefaultValue
+                       {
+                               get { return null; }
+                       }
+
+                       public override Type[] GetOptionalCustomModifiers()
+                       {
+                               return Empty<Type>.Array;
+                       }
+
+                       public override Type[] GetRequiredCustomModifiers()
+                       {
+                               return Empty<Type>.Array;
+                       }
+
+                       public override MemberInfo Member
+                       {
+                               get { return method.IsConstructor ? (MethodBase)new ConstructorInfoImpl(method) : method; }
+                       }
+
+                       public override int MetadataToken
+                       {
+                               get { return 0x8000000; }
+                       }
+
+                       internal override Module Module
+                       {
+                               get { return method.Module; }
+                       }
+               }
+       }
+
+       sealed class ByRefType : ElementHolderType
+       {
+               internal static Type Make(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return type.Module.CanonicalizeType(new ByRefType(type, requiredCustomModifiers, optionalCustomModifiers));
+               }
+
+               private ByRefType(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+                       : base(type, requiredCustomModifiers, optionalCustomModifiers)
+               {
+               }
+
+               public override bool Equals(object o)
+               {
+                       return EqualsHelper(o as ByRefType);
+               }
+
+               public override int GetHashCode()
+               {
+                       return elementType.GetHashCode() * 3;
+               }
+
+               public override Type BaseType
+               {
+                       get { return null; }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return 0; }
+               }
+
+               public override bool IsByRef
+               {
+                       get { return true; }
+               }
+
+               protected override string GetSuffix()
+               {
+                       return "&";
+               }
+
+               protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return Make(type, requiredCustomModifiers, optionalCustomModifiers);
+               }
+       }
+
+       sealed class PointerType : ElementHolderType
+       {
+               internal static Type Make(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return type.Module.CanonicalizeType(new PointerType(type, requiredCustomModifiers, optionalCustomModifiers));
+               }
+
+               private PointerType(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+                       : base(type, requiredCustomModifiers, optionalCustomModifiers)
+               {
+               }
+
+               public override bool Equals(object o)
+               {
+                       return EqualsHelper(o as PointerType);
+               }
+
+               public override int GetHashCode()
+               {
+                       return elementType.GetHashCode() * 7;
+               }
+
+               public override Type BaseType
+               {
+                       get { return null; }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return 0; }
+               }
+
+               public override bool IsPointer
+               {
+                       get { return true; }
+               }
+
+               protected override string GetSuffix()
+               {
+                       return "*";
+               }
+
+               protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+               {
+                       return Make(type, requiredCustomModifiers, optionalCustomModifiers);
+               }
+       }
+
+       sealed class GenericTypeInstance : Type
+       {
+               private readonly Type type;
+               private readonly Type[] args;
+               private readonly Type[][] requiredCustomModifiers;
+               private readonly Type[][] optionalCustomModifiers;
+               private Type baseType;
+               private int token;
+
+               internal static Type Make(Type type, Type[] typeArguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+               {
+                       bool identity = true;
+                       if (type is TypeBuilder || type is BakedType)
+                       {
+                               // a TypeBuiler identity must be instantiated
+                               identity = false;
+                       }
+                       else
+                       {
+                               // we must not instantiate the identity instance, because typeof(Foo<>).MakeGenericType(typeof(Foo<>).GetGenericArguments()) == typeof(Foo<>)
+                               for (int i = 0; i < typeArguments.Length; i++)
+                               {
+                                       if (typeArguments[i] != type.GetGenericTypeArgument(i)
+                                               || !IsEmpty(requiredCustomModifiers, i)
+                                               || !IsEmpty(optionalCustomModifiers, i))
+                                       {
+                                               identity = false;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (identity)
+                       {
+                               return type;
+                       }
+                       else
+                       {
+                               return type.Module.CanonicalizeType(new GenericTypeInstance(type, typeArguments, requiredCustomModifiers, optionalCustomModifiers));
+                       }
+               }
+
+               private static bool IsEmpty(Type[][] mods, int i)
+               {
+                       // we need to be extra careful, because mods doesn't not need to be in canonical format
+                       // (Signature.ReadGenericInst() calls Make() directly, without copying the modifier arrays)
+                       return mods == null || mods[i] == null || mods[i].Length == 0;
+               }
+
+               private GenericTypeInstance(Type type, Type[] args, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+               {
+                       this.type = type;
+                       this.args = args;
+                       this.requiredCustomModifiers = requiredCustomModifiers;
+                       this.optionalCustomModifiers = optionalCustomModifiers;
+               }
+
+               public override bool Equals(object o)
+               {
+                       GenericTypeInstance gt = o as GenericTypeInstance;
+                       return gt != null && gt.type.Equals(type) && Util.ArrayEquals(gt.args, args)
+                               && Util.ArrayEquals(gt.requiredCustomModifiers, requiredCustomModifiers)
+                               && Util.ArrayEquals(gt.optionalCustomModifiers, optionalCustomModifiers);
+               }
+
+               public override int GetHashCode()
+               {
+                       return type.GetHashCode() * 3 ^ Util.GetHashCode(args);
+               }
+
+               public override string AssemblyQualifiedName
+               {
+                       get
+                       {
+                               string fn = FullName;
+                               return fn == null ? null : fn + ", " + type.Assembly.FullName;
+                       }
+               }
+
+               public override Type BaseType
+               {
+                       get
+                       {
+                               if (baseType == null)
+                               {
+                                       Type rawBaseType = type.BaseType;
+                                       if (rawBaseType == null)
+                                       {
+                                               baseType = rawBaseType;
+                                       }
+                                       else
+                                       {
+                                               baseType = rawBaseType.BindTypeParameters(this);
+                                       }
+                               }
+                               return baseType;
+                       }
+               }
+
+               public override bool IsValueType
+               {
+                       get { return type.IsValueType; }
+               }
+
+               public override bool IsVisible
+               {
+                       get
+                       {
+                               if (base.IsVisible)
+                               {
+                                       foreach (Type arg in args)
+                                       {
+                                               if (!arg.IsVisible)
+                                               {
+                                                       return false;
+                                               }
+                                       }
+                                       return true;
+                               }
+                               return false;
+                       }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return type.DeclaringType; }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { return type.Attributes; }
+               }
+
+               internal override void CheckBaked()
+               {
+                       type.CheckBaked();
+               }
+
+               public override FieldInfo[] __GetDeclaredFields()
+               {
+                       FieldInfo[] fields = type.__GetDeclaredFields();
+                       for (int i = 0; i < fields.Length; i++)
+                       {
+                               fields[i] = fields[i].BindTypeParameters(this);
+                       }
+                       return fields;
+               }
+
+               public override Type[] __GetDeclaredInterfaces()
+               {
+                       Type[] interfaces = type.__GetDeclaredInterfaces();
+                       for (int i = 0; i < interfaces.Length; i++)
+                       {
+                               interfaces[i] = interfaces[i].BindTypeParameters(this);
+                       }
+                       return interfaces;
+               }
+
+               public override MethodBase[] __GetDeclaredMethods()
+               {
+                       MethodBase[] methods = type.__GetDeclaredMethods();
+                       for (int i = 0; i < methods.Length; i++)
+                       {
+                               methods[i] = methods[i].BindTypeParameters(this);
+                       }
+                       return methods;
+               }
+
+               public override Type[] __GetDeclaredTypes()
+               {
+                       return type.__GetDeclaredTypes();
+               }
+
+               public override EventInfo[] __GetDeclaredEvents()
+               {
+                       EventInfo[] events = type.__GetDeclaredEvents();
+                       for (int i = 0; i < events.Length; i++)
+                       {
+                               events[i] = events[i].BindTypeParameters(this);
+                       }
+                       return events;
+               }
+
+               public override PropertyInfo[] __GetDeclaredProperties()
+               {
+                       PropertyInfo[] properties = type.__GetDeclaredProperties();
+                       for (int i = 0; i < properties.Length; i++)
+                       {
+                               properties[i] = properties[i].BindTypeParameters(this);
+                       }
+                       return properties;
+               }
+
+               public override __MethodImplMap __GetMethodImplMap()
+               {
+                       __MethodImplMap map = type.__GetMethodImplMap();
+                       map.TargetType = this;
+                       for (int i = 0; i < map.MethodBodies.Length; i++)
+                       {
+                               map.MethodBodies[i] = (MethodInfo)map.MethodBodies[i].BindTypeParameters(this);
+                               for (int j = 0; j < map.MethodDeclarations[i].Length; j++)
+                               {
+                                       Type interfaceType = map.MethodDeclarations[i][j].DeclaringType;
+                                       if (interfaceType.IsGenericType)
+                                       {
+                                               map.MethodDeclarations[i][j] = (MethodInfo)map.MethodDeclarations[i][j].BindTypeParameters(this);
+                                       }
+                               }
+                       }
+                       return map;
+               }
+
+               public override string Namespace
+               {
+                       get { return type.Namespace; }
+               }
+
+               public override Type UnderlyingSystemType
+               {
+                       get { return this; }
+               }
+
+               public override string Name
+               {
+                       get { return type.Name; }
+               }
+
+               public override string FullName
+               {
+                       get
+                       {
+                               if (this.ContainsGenericParameters)
+                               {
+                                       return null;
+                               }
+                               StringBuilder sb = new StringBuilder(base.FullName);
+                               sb.Append('[');
+                               foreach (Type type in args)
+                               {
+                                       sb.Append('[').Append(type.AssemblyQualifiedName.Replace("]", "\\]")).Append(']');
+                               }
+                               sb.Append(']');
+                               return sb.ToString();
+                       }
+               }
+
+               public override string ToString()
+               {
+                       StringBuilder sb = new StringBuilder(type.FullName);
+                       sb.Append('[');
+                       string sep = "";
+                       foreach (Type arg in args)
+                       {
+                               sb.Append(sep);
+                               sb.Append(arg);
+                               sep = ",";
+                       }
+                       sb.Append(']');
+                       return sb.ToString();
+               }
+
+               public override Module Module
+               {
+                       get { return type.Module; }
+               }
+
+               public override bool IsGenericType
+               {
+                       get { return true; }
+               }
+
+               public override Type GetGenericTypeDefinition()
+               {
+                       return type;
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       return Util.Copy(args);
+               }
+
+               public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+               {
+                       return Util.Copy(requiredCustomModifiers ?? new Type[args.Length][]);
+               }
+
+               public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+               {
+                       return Util.Copy(optionalCustomModifiers ?? new Type[args.Length][]);
+               }
+
+               internal override Type GetGenericTypeArgument(int index)
+               {
+                       return args[index];
+               }
+
+               public override bool ContainsGenericParameters
+               {
+                       get
+                       {
+                               foreach (Type type in args)
+                               {
+                                       if (type.ContainsGenericParameters)
+                                       {
+                                               return true;
+                                       }
+                               }
+                               return false;
+                       }
+               }
+
+               public override StructLayoutAttribute StructLayoutAttribute
+               {
+                       get { return type.StructLayoutAttribute; }
+               }
+
+               internal override int GetModuleBuilderToken()
+               {
+                       if (token == 0)
+                       {
+                               token = ((ModuleBuilder)type.Module).ImportType(this);
+                       }
+                       return token;
+               }
+
+               internal override Type BindTypeParameters(IGenericBinder binder)
+               {
+                       for (int i = 0; i < args.Length; i++)
+                       {
+                               Type xarg = args[i].BindTypeParameters(binder);
+                               if (!ReferenceEquals(xarg, args[i]))
+                               {
+                                       Type[] xargs = new Type[args.Length];
+                                       Array.Copy(args, xargs, i);
+                                       xargs[i++] = xarg;
+                                       for (; i < args.Length; i++)
+                                       {
+                                               xargs[i] = args[i].BindTypeParameters(binder);
+                                       }
+                                       return Make(type, xargs, null, null);
+                               }
+                       }
+                       return this;
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return type.GetCustomAttributesData(attributeType);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/TypeNameParser.cs b/mcs/class/IKVM.Reflection/TypeNameParser.cs
new file mode 100644 (file)
index 0000000..d6c18ee
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+  Copyright (C) 2009 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+       struct TypeNameParser
+       {
+               private const string SpecialChars = "\\+,[]*&";
+               private const short SZARRAY = -1;
+               private const short BYREF = -2;
+               private const short POINTER = -3;
+               private readonly string name;
+               private readonly string[] nested;
+               private readonly string assemblyName;
+               private readonly short[] modifiers;
+               private readonly TypeNameParser[] genericParameters;
+
+               internal static string Escape(string name)
+               {
+                       if (name == null)
+                       {
+                               return null;
+                       }
+                       StringBuilder sb = null;
+                       for (int pos = 0; pos < name.Length; pos++)
+                       {
+                               char c = name[pos];
+                               if (SpecialChars.IndexOf(c) != -1)
+                               {
+                                       if (sb == null)
+                                       {
+                                               sb = new StringBuilder(name, 0, pos, name.Length + 3);
+                                       }
+                                       sb.Append('\\').Append(c);
+                               }
+                               else if (sb != null)
+                               {
+                                       sb.Append(c);
+                               }
+                       }
+                       return sb != null ? sb.ToString() : name;
+               }
+
+               internal static string Unescape(string name)
+               {
+                       int pos = name.IndexOf('\\');
+                       if (pos == -1)
+                       {
+                               return name;
+                       }
+                       StringBuilder sb = new StringBuilder(name, 0, pos, name.Length - 1);
+                       for (; pos < name.Length; pos++)
+                       {
+                               char c = name[pos];
+                               if (c == '\\')
+                               {
+                                       c = name[++pos];
+                               }
+                               sb.Append(c);
+                       }
+                       return sb.ToString();
+               }
+
+               internal static TypeNameParser Parse(string typeName, bool throwOnError)
+               {
+                       if (throwOnError)
+                       {
+                               Parser parser = new Parser(typeName);
+                               return new TypeNameParser(ref parser, true);
+                       }
+                       else
+                       {
+                               try
+                               {
+                                       Parser parser = new Parser(typeName);
+                                       return new TypeNameParser(ref parser, true);
+                               }
+                               catch (ArgumentException)
+                               {
+                                       return new TypeNameParser();
+                               }
+                       }
+               }
+
+               private TypeNameParser(ref Parser parser, bool withAssemblyName)
+               {
+                       bool genericParameter = parser.pos != 0;
+                       name = parser.NextNamePart();
+                       nested = null;
+                       parser.ParseNested(ref nested);
+                       genericParameters = null;
+                       parser.ParseGenericParameters(ref genericParameters);
+                       modifiers = null;
+                       parser.ParseModifiers(ref modifiers);
+                       assemblyName = null;
+                       if (withAssemblyName)
+                       {
+                               parser.ParseAssemblyName(genericParameter, ref assemblyName);
+                       }
+               }
+
+               internal bool Error
+               {
+                       get { return name == null; }
+               }
+
+               internal string FirstNamePart
+               {
+                       get { return name; }
+               }
+
+               internal string AssemblyName
+               {
+                       get { return assemblyName; }
+               }
+
+               private struct Parser
+               {
+                       private readonly string typeName;
+                       internal int pos;
+
+                       internal Parser(string typeName)
+                       {
+                               this.typeName = typeName;
+                               this.pos = 0;
+                       }
+
+                       private void Check(bool condition)
+                       {
+                               if (!condition)
+                               {
+                                       throw new ArgumentException("Invalid type name '" + typeName + "'");
+                               }
+                       }
+
+                       private void Consume(char c)
+                       {
+                               Check(pos < typeName.Length && typeName[pos++] == c);
+                       }
+
+                       private bool TryConsume(char c)
+                       {
+                               if (pos < typeName.Length && typeName[pos] == c)
+                               {
+                                       pos++;
+                                       return true;
+                               }
+                               else
+                               {
+                                       return false;
+                               }
+                       }
+
+                       internal string NextNamePart()
+                       {
+                               SkipWhiteSpace();
+                               int start = pos;
+                               for (; pos < typeName.Length; pos++)
+                               {
+                                       char c = typeName[pos];
+                                       if (c == '\\')
+                                       {
+                                               pos++;
+                                               Check(pos < typeName.Length && SpecialChars.IndexOf(typeName[pos]) != -1);
+                                       }
+                                       else if (SpecialChars.IndexOf(c) != -1)
+                                       {
+                                               break;
+                                       }
+                               }
+                               Check(pos - start != 0);
+                               if (start == 0 && pos == typeName.Length)
+                               {
+                                       return typeName;
+                               }
+                               else
+                               {
+                                       return typeName.Substring(start, pos - start);
+                               }
+                       }
+
+                       internal void ParseNested(ref string[] nested)
+                       {
+                               while (TryConsume('+'))
+                               {
+                                       Add(ref nested, NextNamePart());
+                               }
+                       }
+
+                       internal void ParseGenericParameters(ref TypeNameParser[] genericParameters)
+                       {
+                               int saved = pos;
+                               if (TryConsume('['))
+                               {
+                                       SkipWhiteSpace();
+                                       if (TryConsume(']') || TryConsume('*') || TryConsume(','))
+                                       {
+                                               // it's not a generic parameter list, but an array instead
+                                               pos = saved;
+                                               return;
+                                       }
+                                       do
+                                       {
+                                               SkipWhiteSpace();
+                                               if (TryConsume('['))
+                                               {
+                                                       Add(ref genericParameters, new TypeNameParser(ref this, true));
+                                                       Consume(']');
+                                               }
+                                               else
+                                               {
+                                                       Add(ref genericParameters, new TypeNameParser(ref this, false));
+                                               }
+                                       }
+                                       while (TryConsume(','));
+                                       Consume(']');
+                                       SkipWhiteSpace();
+                               }
+                       }
+
+                       internal void ParseModifiers(ref short[] modifiers)
+                       {
+                               while (pos < typeName.Length)
+                               {
+                                       switch (typeName[pos])
+                                       {
+                                               case '*':
+                                                       pos++;
+                                                       Add(ref modifiers, POINTER);
+                                                       break;
+                                               case '&':
+                                                       pos++;
+                                                       Add(ref modifiers, BYREF);
+                                                       break;
+                                               case '[':
+                                                       pos++;
+                                                       Add(ref modifiers, ParseArray());
+                                                       Consume(']');
+                                                       break;
+                                               default:
+                                                       return;
+                                       }
+                                       SkipWhiteSpace();
+                               }
+                       }
+
+                       internal void ParseAssemblyName(bool genericParameter, ref string assemblyName)
+                       {
+                               if (pos < typeName.Length)
+                               {
+                                       if (typeName[pos] == ']' && genericParameter)
+                                       {
+                                               // ok
+                                       }
+                                       else
+                                       {
+                                               Consume(',');
+                                               SkipWhiteSpace();
+                                               if (genericParameter)
+                                               {
+                                                       int start = pos;
+                                                       while (pos < typeName.Length)
+                                                       {
+                                                               char c = typeName[pos];
+                                                               if (c == '\\')
+                                                               {
+                                                                       pos++;
+                                                                       // a backslash itself is not legal in an assembly name, so we don't need to check for an escaped backslash
+                                                                       Check(pos < typeName.Length && typeName[pos++] == ']');
+                                                               }
+                                                               else if (c == ']')
+                                                               {
+                                                                       break;
+                                                               }
+                                                               else
+                                                               {
+                                                                       pos++;
+                                                               }
+                                                       }
+                                                       Check(pos < typeName.Length && typeName[pos] == ']');
+                                                       assemblyName = typeName.Substring(start, pos - start).Replace("\\]", "]");
+                                               }
+                                               else
+                                               {
+                                                       // only when an assembly name is used in a generic type parameter, will it be escaped
+                                                       assemblyName = typeName.Substring(pos);
+                                               }
+                                               Check(assemblyName.Length != 0);
+                                       }
+                               }
+                               else
+                               {
+                                       Check(!genericParameter);
+                               }
+                       }
+
+                       private short ParseArray()
+                       {
+                               SkipWhiteSpace();
+                               Check(pos < typeName.Length);
+                               char c = typeName[pos];
+                               if (c == ']')
+                               {
+                                       return SZARRAY;
+                               }
+                               else if (c == '*')
+                               {
+                                       pos++;
+                                       SkipWhiteSpace();
+                                       return 1;
+                               }
+                               else
+                               {
+                                       short rank = 1;
+                                       while (TryConsume(','))
+                                       {
+                                               Check(rank < short.MaxValue);
+                                               rank++;
+                                               SkipWhiteSpace();
+                                       }
+                                       return rank;
+                               }
+                       }
+
+                       private void SkipWhiteSpace()
+                       {
+                               while (pos < typeName.Length && Char.IsWhiteSpace(typeName[pos]))
+                               {
+                                       pos++;
+                               }
+                       }
+
+                       private static void Add<T>(ref T[] array, T elem)
+                       {
+                               if (array == null)
+                               {
+                                       array = new T[] { elem };
+                                       return;
+                               }
+                               Array.Resize(ref array, array.Length + 1);
+                               array[array.Length - 1] = elem;
+                       }
+               }
+
+               internal Type GetType(Universe universe, Assembly context, bool throwOnError, string originalName)
+               {
+                       Type type;
+                       if (assemblyName != null)
+                       {
+                               Assembly asm = universe.Load(assemblyName, context, throwOnError);
+                               if (asm == null)
+                               {
+                                       return null;
+                               }
+                               type = asm.GetTypeImpl(name);
+                       }
+                       else if (context == null)
+                       {
+                               type = universe.Mscorlib.GetTypeImpl(name);
+                       }
+                       else
+                       {
+                               type = context.GetTypeImpl(name);
+                               if (type == null && context != universe.Mscorlib)
+                               {
+                                       type = universe.Mscorlib.GetTypeImpl(name);
+                               }
+                       }
+                       return Expand(type, context, throwOnError, originalName);
+               }
+
+               internal Type Expand(Type type, Assembly context, bool throwOnError, string originalName)
+               {
+                       if (type == null)
+                       {
+                               if (throwOnError)
+                               {
+                                       throw new TypeLoadException(originalName);
+                               }
+                               return null;
+                       }
+                       if (nested != null)
+                       {
+                               foreach (string nest in nested)
+                               {
+                                       type = type.GetNestedType(nest, BindingFlags.Public | BindingFlags.NonPublic);
+                                       if (type == null)
+                                       {
+                                               if (throwOnError)
+                                               {
+                                                       throw new TypeLoadException(originalName);
+                                               }
+                                               return null;
+                                       }
+                               }
+                       }
+                       if (genericParameters != null)
+                       {
+                               Type[] typeArgs = new Type[genericParameters.Length];
+                               for (int i = 0; i < typeArgs.Length; i++)
+                               {
+                                       typeArgs[i] = genericParameters[i].GetType(type.Assembly.universe, context, throwOnError, originalName);
+                                       if (typeArgs[i] == null)
+                                       {
+                                               return null;
+                                       }
+                               }
+                               type = type.MakeGenericType(typeArgs);
+                       }
+                       if (modifiers != null)
+                       {
+                               foreach (short modifier in modifiers)
+                               {
+                                       switch (modifier)
+                                       {
+                                               case SZARRAY:
+                                                       type = type.MakeArrayType();
+                                                       break;
+                                               case BYREF:
+                                                       type = type.MakeByRefType();
+                                                       break;
+                                               case POINTER:
+                                                       type = type.MakePointerType();
+                                                       break;
+                                               default:
+                                                       type = type.MakeArrayType(modifier);
+                                                       break;
+                                       }
+                               }
+                       }
+                       return type;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Universe.cs b/mcs/class/IKVM.Reflection/Universe.cs
new file mode 100644 (file)
index 0000000..ab63183
--- /dev/null
@@ -0,0 +1,795 @@
+/*
+  Copyright (C) 2009-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security;
+using System.Text;
+using System.Diagnostics;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection
+{
+       public class ResolveEventArgs : EventArgs
+       {
+               private readonly string name;
+               private readonly Assembly requestingAssembly;
+
+               public ResolveEventArgs(string name)
+                       : this(name, null)
+               {
+               }
+
+               public ResolveEventArgs(string name, Assembly requestingAssembly)
+               {
+                       this.name = name;
+                       this.requestingAssembly = requestingAssembly;
+               }
+
+               public string Name
+               {
+                       get { return name; }
+               }
+
+               public Assembly RequestingAssembly
+               {
+                       get { return requestingAssembly; }
+               }
+       }
+
+       public enum AssemblyComparisonResult
+       {
+               Unknown = 0,
+               EquivalentFullMatch = 1,
+               EquivalentWeakNamed = 2,
+               EquivalentFXUnified = 3,
+               EquivalentUnified = 4,
+               NonEquivalentVersion = 5,
+               NonEquivalent = 6,
+               EquivalentPartialMatch = 7,
+               EquivalentPartialWeakNamed = 8,
+               EquivalentPartialUnified = 9,
+               EquivalentPartialFXUnified = 10,
+               NonEquivalentPartialVersion = 11,
+       }
+
+       public delegate Assembly ResolveEventHandler(object sender, ResolveEventArgs args);
+
+       public sealed class Universe : IDisposable
+       {
+               internal readonly Dictionary<Type, Type> canonicalizedTypes = new Dictionary<Type, Type>();
+               private readonly List<Assembly> assemblies = new List<Assembly>();
+               private readonly List<AssemblyBuilder> dynamicAssemblies = new List<AssemblyBuilder>();
+               private readonly Dictionary<string, Assembly> assembliesByName = new Dictionary<string, Assembly>();
+               private readonly Dictionary<System.Type, Type> importedTypes = new Dictionary<System.Type, Type>();
+               private Type typeof_System_Object;
+               private Type typeof_System_ValueType;
+               private Type typeof_System_Enum;
+               private Type typeof_System_Void;
+               private Type typeof_System_Boolean;
+               private Type typeof_System_Char;
+               private Type typeof_System_SByte;
+               private Type typeof_System_Byte;
+               private Type typeof_System_Int16;
+               private Type typeof_System_UInt16;
+               private Type typeof_System_Int32;
+               private Type typeof_System_UInt32;
+               private Type typeof_System_Int64;
+               private Type typeof_System_UInt64;
+               private Type typeof_System_Single;
+               private Type typeof_System_Double;
+               private Type typeof_System_String;
+               private Type typeof_System_IntPtr;
+               private Type typeof_System_UIntPtr;
+               private Type typeof_System_TypedReference;
+               private Type typeof_System_Type;
+               private Type typeof_System_Array;
+               private Type typeof_System_DateTime;
+               private Type typeof_System_DBNull;
+               private Type typeof_System_Decimal;
+               private Type typeof_System_NonSerializedAttribute;
+               private Type typeof_System_SerializableAttribute;
+               private Type typeof_System_AttributeUsageAttribute;
+               private Type typeof_System_Reflection_AssemblyCultureAttribute;
+               private Type typeof_System_Runtime_InteropServices_DllImportAttribute;
+               private Type typeof_System_Runtime_InteropServices_FieldOffsetAttribute;
+               private Type typeof_System_Runtime_InteropServices_InAttribute;
+               private Type typeof_System_Runtime_InteropServices_MarshalAsAttribute;
+               private Type typeof_System_Runtime_InteropServices_UnmanagedType;
+               private Type typeof_System_Runtime_InteropServices_VarEnum;
+               private Type typeof_System_Runtime_InteropServices_OutAttribute;
+               private Type typeof_System_Runtime_InteropServices_StructLayoutAttribute;
+               private Type typeof_System_Runtime_InteropServices_OptionalAttribute;
+               private Type typeof_System_Runtime_InteropServices_PreserveSigAttribute;
+               private Type typeof_System_Runtime_InteropServices_ComImportAttribute;
+               private Type typeof_System_Runtime_CompilerServices_DecimalConstantAttribute;
+               private Type typeof_System_Runtime_CompilerServices_SpecialNameAttribute;
+               private Type typeof_System_Runtime_CompilerServices_MethodImplAttribute;
+               private Type typeof_System_Security_SuppressUnmanagedCodeSecurityAttribute;
+               private Type typeof_System_Reflection_AssemblyCopyrightAttribute;
+               private Type typeof_System_Reflection_AssemblyTrademarkAttribute;
+               private Type typeof_System_Reflection_AssemblyProductAttribute;
+               private Type typeof_System_Reflection_AssemblyCompanyAttribute;
+               private Type typeof_System_Reflection_AssemblyDescriptionAttribute;
+               private Type typeof_System_Reflection_AssemblyTitleAttribute;
+               private Type typeof_System_Reflection_AssemblyInformationalVersionAttribute;
+               private Type typeof_System_Reflection_AssemblyFileVersionAttribute;
+               private Type typeof_System_Security_Permissions_CodeAccessSecurityAttribute;
+               private Type typeof_System_Security_Permissions_HostProtectionAttribute;
+               private Type typeof_System_Security_Permissions_PermissionSetAttribute;
+               private Type typeof_System_Security_Permissions_SecurityAction;
+               private List<ResolveEventHandler> resolvers = new List<ResolveEventHandler>();
+
+               internal Assembly Mscorlib
+               {
+                       get { return Load("mscorlib"); }
+               }
+
+               private Type ImportMscorlibType(System.Type type)
+               {
+                       return Mscorlib.GetTypeImpl(type.FullName);
+               }
+
+               internal Type System_Object
+               {
+                       get { return typeof_System_Object ?? (typeof_System_Object = ImportMscorlibType(typeof(System.Object))); }
+               }
+
+               internal Type System_ValueType
+               {
+                       get { return typeof_System_ValueType ?? (typeof_System_ValueType = ImportMscorlibType(typeof(System.ValueType))); }
+               }
+
+               internal Type System_Enum
+               {
+                       get { return typeof_System_Enum ?? (typeof_System_Enum = ImportMscorlibType(typeof(System.Enum))); }
+               }
+
+               internal Type System_Void
+               {
+                       get { return typeof_System_Void ?? (typeof_System_Void = ImportMscorlibType(typeof(void))); }
+               }
+
+               internal Type System_Boolean
+               {
+                       get { return typeof_System_Boolean ?? (typeof_System_Boolean = ImportMscorlibType(typeof(System.Boolean))); }
+               }
+
+               internal Type System_Char
+               {
+                       get { return typeof_System_Char ?? (typeof_System_Char = ImportMscorlibType(typeof(System.Char))); }
+               }
+
+               internal Type System_SByte
+               {
+                       get { return typeof_System_SByte ?? (typeof_System_SByte = ImportMscorlibType(typeof(System.SByte))); }
+               }
+
+               internal Type System_Byte
+               {
+                       get { return typeof_System_Byte ?? (typeof_System_Byte = ImportMscorlibType(typeof(System.Byte))); }
+               }
+
+               internal Type System_Int16
+               {
+                       get { return typeof_System_Int16 ?? (typeof_System_Int16 = ImportMscorlibType(typeof(System.Int16))); }
+               }
+
+               internal Type System_UInt16
+               {
+                       get { return typeof_System_UInt16 ?? (typeof_System_UInt16 = ImportMscorlibType(typeof(System.UInt16))); }
+               }
+
+               internal Type System_Int32
+               {
+                       get { return typeof_System_Int32 ?? (typeof_System_Int32 = ImportMscorlibType(typeof(System.Int32))); }
+               }
+
+               internal Type System_UInt32
+               {
+                       get { return typeof_System_UInt32 ?? (typeof_System_UInt32 = ImportMscorlibType(typeof(System.UInt32))); }
+               }
+
+               internal Type System_Int64
+               {
+                       get { return typeof_System_Int64 ?? (typeof_System_Int64 = ImportMscorlibType(typeof(System.Int64))); }
+               }
+
+               internal Type System_UInt64
+               {
+                       get { return typeof_System_UInt64 ?? (typeof_System_UInt64 = ImportMscorlibType(typeof(System.UInt64))); }
+               }
+
+               internal Type System_Single
+               {
+                       get { return typeof_System_Single ?? (typeof_System_Single = ImportMscorlibType(typeof(System.Single))); }
+               }
+
+               internal Type System_Double
+               {
+                       get { return typeof_System_Double ?? (typeof_System_Double = ImportMscorlibType(typeof(System.Double))); }
+               }
+
+               internal Type System_String
+               {
+                       get { return typeof_System_String ?? (typeof_System_String = ImportMscorlibType(typeof(System.String))); }
+               }
+
+               internal Type System_IntPtr
+               {
+                       get { return typeof_System_IntPtr ?? (typeof_System_IntPtr = ImportMscorlibType(typeof(System.IntPtr))); }
+               }
+
+               internal Type System_UIntPtr
+               {
+                       get { return typeof_System_UIntPtr ?? (typeof_System_UIntPtr = ImportMscorlibType(typeof(System.UIntPtr))); }
+               }
+
+               internal Type System_TypedReference
+               {
+                       get { return typeof_System_TypedReference ?? (typeof_System_TypedReference = ImportMscorlibType(typeof(System.TypedReference))); }
+               }
+
+               internal Type System_Type
+               {
+                       get { return typeof_System_Type ?? (typeof_System_Type = ImportMscorlibType(typeof(System.Type))); }
+               }
+
+               internal Type System_Array
+               {
+                       get { return typeof_System_Array ?? (typeof_System_Array = ImportMscorlibType(typeof(System.Array))); }
+               }
+
+               internal Type System_DateTime
+               {
+                       get { return typeof_System_DateTime ?? (typeof_System_DateTime = ImportMscorlibType(typeof(System.DateTime))); }
+               }
+
+               internal Type System_DBNull
+               {
+                       get { return typeof_System_DBNull ?? (typeof_System_DBNull = ImportMscorlibType(typeof(System.DBNull))); }
+               }
+
+               internal Type System_Decimal
+               {
+                       get { return typeof_System_Decimal ?? (typeof_System_Decimal = ImportMscorlibType(typeof(System.Decimal))); }
+               }
+
+               internal Type System_NonSerializedAttribute
+               {
+                       get { return typeof_System_NonSerializedAttribute ?? (typeof_System_NonSerializedAttribute = ImportMscorlibType(typeof(System.NonSerializedAttribute))); }
+               }
+
+               internal Type System_SerializableAttribute
+               {
+                       get { return typeof_System_SerializableAttribute ?? (typeof_System_SerializableAttribute = ImportMscorlibType(typeof(System.SerializableAttribute))); }
+               }
+
+               internal Type System_AttributeUsageAttribute
+               {
+                       get { return typeof_System_AttributeUsageAttribute ?? (typeof_System_AttributeUsageAttribute = ImportMscorlibType(typeof(System.AttributeUsageAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyCultureAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyCultureAttribute ?? (typeof_System_Reflection_AssemblyCultureAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyCultureAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_DllImportAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_DllImportAttribute ?? (typeof_System_Runtime_InteropServices_DllImportAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.DllImportAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_FieldOffsetAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_FieldOffsetAttribute ?? (typeof_System_Runtime_InteropServices_FieldOffsetAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.FieldOffsetAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_InAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_InAttribute ?? (typeof_System_Runtime_InteropServices_InAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.InAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_MarshalAsAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_MarshalAsAttribute ?? (typeof_System_Runtime_InteropServices_MarshalAsAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.MarshalAsAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_UnmanagedType
+               {
+                       get { return typeof_System_Runtime_InteropServices_UnmanagedType ?? (typeof_System_Runtime_InteropServices_UnmanagedType = ImportMscorlibType(typeof(System.Runtime.InteropServices.UnmanagedType))); }
+               }
+
+               internal Type System_Runtime_InteropServices_VarEnum
+               {
+                       get { return typeof_System_Runtime_InteropServices_VarEnum ?? (typeof_System_Runtime_InteropServices_VarEnum = ImportMscorlibType(typeof(System.Runtime.InteropServices.VarEnum))); }
+               }
+
+               internal Type System_Runtime_InteropServices_OutAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_OutAttribute ?? (typeof_System_Runtime_InteropServices_OutAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.OutAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_StructLayoutAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_StructLayoutAttribute ?? (typeof_System_Runtime_InteropServices_StructLayoutAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.StructLayoutAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_OptionalAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_OptionalAttribute ?? (typeof_System_Runtime_InteropServices_OptionalAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.OptionalAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_PreserveSigAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_PreserveSigAttribute ?? (typeof_System_Runtime_InteropServices_PreserveSigAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.PreserveSigAttribute))); }
+               }
+
+               internal Type System_Runtime_InteropServices_ComImportAttribute
+               {
+                       get { return typeof_System_Runtime_InteropServices_ComImportAttribute ?? (typeof_System_Runtime_InteropServices_ComImportAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.ComImportAttribute))); }
+               }
+
+               internal Type System_Runtime_CompilerServices_DecimalConstantAttribute
+               {
+                       get { return typeof_System_Runtime_CompilerServices_DecimalConstantAttribute ?? (typeof_System_Runtime_CompilerServices_DecimalConstantAttribute = ImportMscorlibType(typeof(System.Runtime.CompilerServices.DecimalConstantAttribute))); }
+               }
+
+               internal Type System_Runtime_CompilerServices_SpecialNameAttribute
+               {
+                       get { return typeof_System_Runtime_CompilerServices_SpecialNameAttribute ?? (typeof_System_Runtime_CompilerServices_SpecialNameAttribute = ImportMscorlibType(typeof(System.Runtime.CompilerServices.SpecialNameAttribute))); }
+               }
+
+               internal Type System_Runtime_CompilerServices_MethodImplAttribute
+               {
+                       get { return typeof_System_Runtime_CompilerServices_MethodImplAttribute ?? (typeof_System_Runtime_CompilerServices_MethodImplAttribute = ImportMscorlibType(typeof(System.Runtime.CompilerServices.MethodImplAttribute))); }
+               }
+
+               internal Type System_Security_SuppressUnmanagedCodeSecurityAttribute
+               {
+                       get { return typeof_System_Security_SuppressUnmanagedCodeSecurityAttribute ?? (typeof_System_Security_SuppressUnmanagedCodeSecurityAttribute = ImportMscorlibType(typeof(System.Security.SuppressUnmanagedCodeSecurityAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyCopyrightAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyCopyrightAttribute ?? (typeof_System_Reflection_AssemblyCopyrightAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyCopyrightAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyTrademarkAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyTrademarkAttribute ?? (typeof_System_Reflection_AssemblyTrademarkAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyTrademarkAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyProductAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyProductAttribute ?? (typeof_System_Reflection_AssemblyProductAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyProductAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyCompanyAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyCompanyAttribute ?? (typeof_System_Reflection_AssemblyCompanyAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyCompanyAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyDescriptionAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyDescriptionAttribute ?? (typeof_System_Reflection_AssemblyDescriptionAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyDescriptionAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyTitleAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyTitleAttribute ?? (typeof_System_Reflection_AssemblyTitleAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyTitleAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyInformationalVersionAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyInformationalVersionAttribute ?? (typeof_System_Reflection_AssemblyInformationalVersionAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyInformationalVersionAttribute))); }
+               }
+
+               internal Type System_Reflection_AssemblyFileVersionAttribute
+               {
+                       get { return typeof_System_Reflection_AssemblyFileVersionAttribute ?? (typeof_System_Reflection_AssemblyFileVersionAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyFileVersionAttribute))); }
+               }
+
+               internal Type System_Security_Permissions_CodeAccessSecurityAttribute
+               {
+                       get { return typeof_System_Security_Permissions_CodeAccessSecurityAttribute ?? (typeof_System_Security_Permissions_CodeAccessSecurityAttribute = ImportMscorlibType(typeof(System.Security.Permissions.CodeAccessSecurityAttribute))); }
+               }
+
+               internal Type System_Security_Permissions_HostProtectionAttribute
+               {
+                       get { return typeof_System_Security_Permissions_HostProtectionAttribute ?? (typeof_System_Security_Permissions_HostProtectionAttribute = ImportMscorlibType(typeof(System.Security.Permissions.HostProtectionAttribute))); }
+               }
+
+               internal Type System_Security_Permissions_PermissionSetAttribute
+               {
+                       get { return typeof_System_Security_Permissions_PermissionSetAttribute ?? (typeof_System_Security_Permissions_PermissionSetAttribute = ImportMscorlibType(typeof(System.Security.Permissions.PermissionSetAttribute))); }
+               }
+
+               internal Type System_Security_Permissions_SecurityAction
+               {
+                       get { return typeof_System_Security_Permissions_SecurityAction ?? (typeof_System_Security_Permissions_SecurityAction = ImportMscorlibType(typeof(System.Security.Permissions.SecurityAction))); }
+               }
+
+               internal bool HasMscorlib
+               {
+                       get { return GetLoadedAssembly("mscorlib") != null; }
+               }
+
+               public event ResolveEventHandler AssemblyResolve
+               {
+                       add { resolvers.Add(value); }
+                       remove { resolvers.Remove(value); }
+               }
+
+               public Type Import(System.Type type)
+               {
+                       Type imported;
+                       if (!importedTypes.TryGetValue(type, out imported))
+                       {
+                               imported = ImportImpl(type);
+                               if (imported != null)
+                               {
+                                       importedTypes.Add(type, imported);
+                               }
+                       }
+                       return imported;
+               }
+
+               private Type ImportImpl(System.Type type)
+               {
+                       if (type.Assembly == typeof(IKVM.Reflection.Type).Assembly)
+                       {
+                               throw new ArgumentException("Did you really want to import " + type.FullName + "?");
+                       }
+                       if (type.HasElementType)
+                       {
+                               if (type.IsArray)
+                               {
+                                       if (type.Name.EndsWith("[]"))
+                                       {
+                                               return Import(type.GetElementType()).MakeArrayType();
+                                       }
+                                       else
+                                       {
+                                               return Import(type.GetElementType()).MakeArrayType(type.GetArrayRank());
+                                       }
+                               }
+                               else if (type.IsByRef)
+                               {
+                                       return Import(type.GetElementType()).MakeByRefType();
+                               }
+                               else if (type.IsPointer)
+                               {
+                                       return Import(type.GetElementType()).MakePointerType();
+                               }
+                               else
+                               {
+                                       throw new InvalidOperationException();
+                               }
+                       }
+                       else if (type.IsGenericParameter)
+                       {
+                               if (type.DeclaringMethod != null)
+                               {
+                                       throw new NotImplementedException();
+                               }
+                               else
+                               {
+                                       return Import(type.DeclaringType).GetGenericArguments()[type.GenericParameterPosition];
+                               }
+                       }
+                       else if (type.IsGenericType && !type.IsGenericTypeDefinition)
+                       {
+                               System.Type[] args = type.GetGenericArguments();
+                               Type[] importedArgs = new Type[args.Length];
+                               for (int i = 0; i < args.Length; i++)
+                               {
+                                       importedArgs[i] = Import(args[i]);
+                               }
+                               return Import(type.GetGenericTypeDefinition()).MakeGenericType(importedArgs);
+                       }
+                       else
+                       {
+                               return Import(type.Assembly).GetType(type.FullName);
+                       }
+               }
+
+               private Assembly Import(System.Reflection.Assembly asm)
+               {
+                       return Load(asm.FullName);
+               }
+
+               public RawModule OpenRawModule(string path)
+               {
+                       path = Path.GetFullPath(path);
+                       return OpenRawModule(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read), path);
+               }
+
+               public RawModule OpenRawModule(Stream stream, string location)
+               {
+                       if (!stream.CanRead || !stream.CanSeek)
+                       {
+                               throw new NotSupportedException();
+                       }
+                       return new RawModule(new ModuleReader(null, this, stream, location));
+               }
+
+               public Assembly LoadAssembly(RawModule module)
+               {
+                       string refname = module.GetAssemblyName().FullName;
+                       Assembly asm = GetLoadedAssembly(refname);
+                       if (asm == null)
+                       {
+                               asm = module.ToAssembly();
+                               assemblies.Add(asm);
+                       }
+                       return asm;
+               }
+
+               public Assembly LoadFile(string path)
+               {
+                       try
+                       {
+                               using (RawModule module = OpenRawModule(path))
+                               {
+                                       return LoadAssembly(module);
+                               }
+                       }
+                       catch (IOException x)
+                       {
+                               throw new FileNotFoundException(x.Message, x);
+                       }
+                       catch (UnauthorizedAccessException x)
+                       {
+                               throw new FileNotFoundException(x.Message, x);
+                       }
+               }
+
+               private Assembly GetLoadedAssembly(string refname)
+               {
+                       Assembly asm;
+                       if (!assembliesByName.TryGetValue(refname, out asm))
+                       {
+                               for (int i = 0; i < assemblies.Count; i++)
+                               {
+                                       AssemblyComparisonResult result;
+                                       // We won't allow FX unification here, because our own (non-Fusion) implementation of CompareAssemblyIdentity doesn't support it and
+                                       // we don't want to create a fundamental functional difference based on that.
+                                       if (CompareAssemblyIdentity(refname, false, assemblies[i].FullName, false, out result) && result != AssemblyComparisonResult.EquivalentFXUnified)
+                                       {
+                                               asm = assemblies[i];
+                                               assembliesByName.Add(refname, asm);
+                                               break;
+                                       }
+                               }
+                       }
+                       return asm;
+               }
+
+               private Assembly GetDynamicAssembly(string refname)
+               {
+                       foreach (AssemblyBuilder asm in dynamicAssemblies)
+                       {
+                               AssemblyComparisonResult result;
+                               // We won't allow FX unification here, because our own (non-Fusion) implementation of CompareAssemblyIdentity doesn't support it and
+                               // we don't want to create a fundamental functional difference based on that.
+                               if (CompareAssemblyIdentity(refname, false, asm.FullName, false, out result) && result != AssemblyComparisonResult.EquivalentFXUnified)
+                               {
+                                       return asm;
+                               }
+                       }
+                       return null;
+               }
+
+               public Assembly Load(string refname)
+               {
+                       return Load(refname, null, true);
+               }
+
+               internal Assembly Load(string refname, Assembly requestingAssembly, bool throwOnError)
+               {
+                       Assembly asm = GetLoadedAssembly(refname);
+                       if (asm != null)
+                       {
+                               return asm;
+                       }
+                       if (resolvers.Count == 0)
+                       {
+                               asm = DefaultResolver(refname, throwOnError);
+                       }
+                       else
+                       {
+                               ResolveEventArgs args = new ResolveEventArgs(refname, requestingAssembly);
+                               foreach (ResolveEventHandler evt in resolvers)
+                               {
+                                       asm = evt(this, args);
+                                       if (asm != null)
+                                       {
+                                               break;
+                                       }
+                               }
+                               if (asm == null)
+                               {
+                                       asm = GetDynamicAssembly(refname);
+                               }
+                       }
+                       if (asm != null)
+                       {
+                               string defname = asm.FullName;
+                               if (refname != defname)
+                               {
+                                       assembliesByName.Add(refname, asm);
+                               }
+                               return asm;
+                       }
+                       if (throwOnError)
+                       {
+                               throw new FileNotFoundException(refname);
+                       }
+                       return null;
+               }
+
+               private Assembly DefaultResolver(string refname, bool throwOnError)
+               {
+                       Assembly asm = GetDynamicAssembly(refname);
+                       if (asm != null)
+                       {
+                               return asm;
+                       }
+                       string fileName;
+                       if (throwOnError)
+                       {
+                               try
+                               {
+                                       fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location;
+                               }
+                               catch (System.BadImageFormatException x)
+                               {
+                                       throw new BadImageFormatException(x.Message, x);
+                               }
+                       }
+                       else
+                       {
+                               try
+                               {
+                                       fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location;
+                               }
+                               catch (System.BadImageFormatException x)
+                               {
+                                       throw new BadImageFormatException(x.Message, x);
+                               }
+                               catch (FileNotFoundException)
+                               {
+                                       // we intentionally only swallow the FileNotFoundException, if the file exists but isn't a valid assembly,
+                                       // we should throw an exception
+                                       return null;
+                               }
+                       }
+                       return LoadFile(fileName);
+               }
+
+               public Type GetType(string assemblyQualifiedTypeName)
+               {
+                       // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
+                       // import that assembly and pass it as the context, but implicitly importing is considered evil
+                       return GetType(null, assemblyQualifiedTypeName, false);
+               }
+
+               public Type GetType(string assemblyQualifiedTypeName, bool throwOnError)
+               {
+                       // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
+                       // import that assembly and pass it as the context, but implicitly importing is considered evil
+                       return GetType(null, assemblyQualifiedTypeName, throwOnError);
+               }
+
+               // note that context is slightly different from the calling assembly (System.Type.GetType),
+               // because context is passed to the AssemblyResolve event as the RequestingAssembly
+               public Type GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError)
+               {
+                       TypeNameParser parser = TypeNameParser.Parse(assemblyQualifiedTypeName, throwOnError);
+                       if (parser.Error)
+                       {
+                               return null;
+                       }
+                       return parser.GetType(this, context, throwOnError, assemblyQualifiedTypeName);
+               }
+
+               public Assembly[] GetAssemblies()
+               {
+                       Assembly[] array = new Assembly[assemblies.Count + dynamicAssemblies.Count];
+                       assemblies.CopyTo(array);
+                       for (int i = 0, j = assemblies.Count; j < array.Length; i++, j++)
+                       {
+                               array[j] = dynamicAssemblies[i];
+                       }
+                       return array;
+               }
+
+               // this is equivalent to the Fusion CompareAssemblyIdentity API
+               public bool CompareAssemblyIdentity(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
+               {
+                       return Fusion.CompareAssemblyIdentity(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result);
+               }
+
+               public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
+               {
+                       return DefineDynamicAssemblyImpl(name, access, null, null, null, null);
+               }
+
+               public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir)
+               {
+                       return DefineDynamicAssemblyImpl(name, access, dir, null, null, null);
+               }
+
+#if NET_4_0
+               [Obsolete]
+#endif
+               public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
+               {
+                       return DefineDynamicAssemblyImpl(name, access, dir, requiredPermissions, optionalPermissions, refusedPermissions);
+               }
+
+               private AssemblyBuilder DefineDynamicAssemblyImpl(AssemblyName name, AssemblyBuilderAccess access, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
+               {
+                       AssemblyBuilder asm = new AssemblyBuilder(this, name, dir, requiredPermissions, optionalPermissions, refusedPermissions);
+                       dynamicAssemblies.Add(asm);
+                       return asm;
+               }
+
+               internal void RenameAssembly(Assembly assembly, AssemblyName oldName)
+               {
+                       List<string> remove = new List<string>();
+                       foreach (KeyValuePair<string, Assembly> kv in assembliesByName)
+                       {
+                               if (kv.Value == assembly)
+                               {
+                                       remove.Add(kv.Key);
+                               }
+                       }
+                       foreach (string key in remove)
+                       {
+                               assembliesByName.Remove(key);
+                       }
+               }
+
+               public void Dispose()
+               {
+                       foreach (Assembly asm in assemblies)
+                       {
+                               foreach (Module mod in asm.GetLoadedModules())
+                               {
+                                       mod.Dispose();
+                               }
+                       }
+                       foreach (AssemblyBuilder asm in dynamicAssemblies)
+                       {
+                               foreach (Module mod in asm.GetLoadedModules())
+                               {
+                                       mod.Dispose();
+                               }
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Util.cs b/mcs/class/IKVM.Reflection/Util.cs
new file mode 100644 (file)
index 0000000..a471eed
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+  Copyright (C) 2008-2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection
+{
+       public interface ICustomAttributeProvider
+       {
+               bool IsDefined(Type attributeType, bool inherit);
+               IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit);
+       }
+
+       [Serializable]
+       public sealed class FileFormatLimitationExceededException : InvalidOperationException
+       {
+               public const int META_E_STRINGSPACE_FULL = unchecked((int)0x80131198);
+
+               public FileFormatLimitationExceededException(string message, int hresult)
+                       : base(message)
+               {
+                       this.HResult = hresult;
+               }
+
+               private FileFormatLimitationExceededException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+                       : base(info, context)
+               {
+               }
+
+               public int ErrorCode
+               {
+                       get { return this.HResult; }
+               }
+       }
+
+       [Serializable]
+       public sealed class Missing : ISerializable
+       {
+               public static readonly Missing Value = new Missing();
+
+               private Missing() { }
+
+               void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+               {
+                       info.SetType(typeof(SingletonSerializationHelper));
+               }
+
+               [Serializable]
+               private sealed class SingletonSerializationHelper : IObjectReference
+               {
+                       public object GetRealObject(StreamingContext context)
+                       {
+                               return Value;
+                       }
+               }
+       }
+
+       static class Empty<T>
+       {
+               internal static readonly T[] Array = new T[0];
+       }
+
+       static class Util
+       {
+               internal static Type[] Copy(Type[] array)
+               {
+                       if (array == null || array.Length == 0)
+                       {
+                               return Type.EmptyTypes;
+                       }
+                       Type[] copy = new Type[array.Length];
+                       Array.Copy(array, copy, array.Length);
+                       return copy;
+               }
+
+               internal static Type[][] Copy(Type[][] types)
+               {
+                       if (types == null || types.Length == 0)
+                       {
+                               return types;
+                       }
+                       Type[][] newArray = new Type[types.Length][];
+                       for (int i = 0; i < newArray.Length; i++)
+                       {
+                               newArray[i] = Copy(types[i]);
+                       }
+                       return newArray;
+               }
+
+               internal static T[] ToArray<T, V>(List<V> list, T[] empty) where V : T
+               {
+                       if (list == null || list.Count == 0)
+                       {
+                               return empty;
+                       }
+                       T[] array = new T[list.Count];
+                       for (int i = 0; i < array.Length; i++)
+                       {
+                               array[i] = list[i];
+                       }
+                       return array;
+               }
+
+               // note that an empty array matches a null reference
+               internal static bool ArrayEquals(Type[] t1, Type[] t2)
+               {
+                       if (t1 == t2)
+                       {
+                               return true;
+                       }
+                       if (t1 == null)
+                       {
+                               return t2.Length == 0;
+                       }
+                       else if (t2 == null)
+                       {
+                               return t1.Length == 0;
+                       }
+                       if (t1.Length == t2.Length)
+                       {
+                               for (int i = 0; i < t1.Length; i++)
+                               {
+                                       if (!TypeEquals(t1[i], t2[i]))
+                                       {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               internal static bool ArrayEquals(Type[][] t1, Type[][] t2)
+               {
+                       if (t1 == t2)
+                       {
+                               return true;
+                       }
+                       if (t1 == null)
+                       {
+                               return t2.Length == 0;
+                       }
+                       else if (t2 == null)
+                       {
+                               return t1.Length == 0;
+                       }
+                       if (t1.Length == t2.Length)
+                       {
+                               for (int i = 0; i < t1.Length; i++)
+                               {
+                                       if (!ArrayEquals(t1[i], t2[i]))
+                                       {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               internal static bool ArrayEquals(Type[][][] t1, Type[][][] t2)
+               {
+                       if (t1 == t2)
+                       {
+                               return true;
+                       }
+                       if (t1 == null)
+                       {
+                               return t2.Length == 0;
+                       }
+                       else if (t2 == null)
+                       {
+                               return t1.Length == 0;
+                       }
+                       if (t1.Length == t2.Length)
+                       {
+                               for (int i = 0; i < t1.Length; i++)
+                               {
+                                       if (!ArrayEquals(t1[i], t2[i]))
+                                       {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               internal static bool TypeEquals(Type t1, Type t2)
+               {
+                       if (t1 == t2)
+                       {
+                               return true;
+                       }
+                       if (t1 == null)
+                       {
+                               return false;
+                       }
+                       return t1.Equals(t2);
+               }
+
+               internal static int GetHashCode(Type[] types)
+               {
+                       if (types == null)
+                       {
+                               return 0;
+                       }
+                       int h = 0;
+                       foreach (Type t in types)
+                       {
+                               if (t != null)
+                               {
+                                       h *= 3;
+                                       h ^= t.GetHashCode();
+                               }
+                       }
+                       return h;
+               }
+
+               internal static int GetHashCode(Type[][] types)
+               {
+                       int h = 0;
+                       if (types != null)
+                       {
+                               foreach (Type[] array in types)
+                               {
+                                       h ^= GetHashCode(array);
+                               }
+                       }
+                       return h;
+               }
+
+               internal static int GetHashCode(Type[][][] types)
+               {
+                       int h = 0;
+                       if (types != null)
+                       {
+                               foreach (Type[][] array in types)
+                               {
+                                       h ^= GetHashCode(array);
+                               }
+                       }
+                       return h;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/ByteBuffer.cs b/mcs/class/IKVM.Reflection/Writer/ByteBuffer.cs
new file mode 100644 (file)
index 0000000..6b06a7d
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+       sealed class ByteBuffer
+       {
+               private byte[] buffer;
+               private int pos;
+               private int __length;   // __length is only valid if > pos, otherwise pos is the current length
+
+               internal ByteBuffer(int initialCapacity)
+               {
+                       buffer = new byte[initialCapacity];
+               }
+
+               private ByteBuffer(byte[] wrap, int length)
+               {
+                       this.buffer = wrap;
+                       this.pos = length;
+               }
+
+               internal int Position
+               {
+                       get { return pos; }
+                       set
+                       {
+                               if (value > this.Length || value > buffer.Length)
+                                       throw new ArgumentOutOfRangeException();
+                               __length = Math.Max(__length, pos);
+                               pos = value;
+                       }
+               }
+
+               internal int Length
+               {
+                       get { return Math.Max(pos, __length); }
+               }
+
+               private void Grow(int minGrow)
+               {
+                       byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
+                       Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length);
+                       buffer = newbuf;
+               }
+
+               // NOTE this does not advance the position
+               internal int GetInt32AtCurrentPosition()
+               {
+                       return buffer[pos]
+                               + (buffer[pos + 1] << 8)
+                               + (buffer[pos + 2] << 16)
+                               + (buffer[pos + 3] << 24);
+               }
+
+               // NOTE this does not advance the position
+               internal byte GetByteAtCurrentPosition()
+               {
+                       return buffer[pos];
+               }
+
+               internal void Write(byte[] value)
+               {
+                       if (pos + value.Length > buffer.Length)
+                               Grow(value.Length);
+                       Buffer.BlockCopy(value, 0, buffer, pos, value.Length);
+                       pos += value.Length;
+               }
+
+               internal void Write(byte value)
+               {
+                       if (pos == buffer.Length)
+                               Grow(1);
+                       buffer[pos++] = value;
+               }
+
+               internal void Write(sbyte value)
+               {
+                       Write((byte)value);
+               }
+
+               internal void Write(ushort value)
+               {
+                       Write((short)value);
+               }
+
+               internal void Write(short value)
+               {
+                       if (pos + 2 > buffer.Length)
+                               Grow(2);
+                       buffer[pos++] = (byte)value;
+                       buffer[pos++] = (byte)(value >> 8);
+               }
+
+               internal void Write(uint value)
+               {
+                       Write((int)value);
+               }
+       
+               internal void Write(int value)
+               {
+                       if (pos + 4 > buffer.Length)
+                               Grow(4);
+                       buffer[pos++] = (byte)value;
+                       buffer[pos++] = (byte)(value >> 8);
+                       buffer[pos++] = (byte)(value >> 16);
+                       buffer[pos++] = (byte)(value >> 24);
+               }
+
+               internal void Write(ulong value)
+               {
+                       Write((long)value);
+               }
+
+               internal void Write(long value)
+               {
+                       if (pos + 8 > buffer.Length)
+                               Grow(8);
+                       buffer[pos++] = (byte)value;
+                       buffer[pos++] = (byte)(value >> 8);
+                       buffer[pos++] = (byte)(value >> 16);
+                       buffer[pos++] = (byte)(value >> 24);
+                       buffer[pos++] = (byte)(value >> 32);
+                       buffer[pos++] = (byte)(value >> 40);
+                       buffer[pos++] = (byte)(value >> 48);
+                       buffer[pos++] = (byte)(value >> 56);
+               }
+
+               internal void Write(float value)
+               {
+                       Write(BitConverter.GetBytes(value));
+               }
+
+               internal void Write(double value)
+               {
+                       Write(BitConverter.DoubleToInt64Bits(value));
+               }
+
+               internal void Write(string str)
+               {
+                       if (str == null)
+                       {
+                               Write((byte)0xFF);
+                       }
+                       else
+                       {
+                               byte[] buf = Encoding.UTF8.GetBytes(str);
+                               WriteCompressedInt(buf.Length);
+                               Write(buf);
+                       }
+               }
+
+               internal void WriteCompressedInt(int value)
+               {
+                       if (value <= 0x7F)
+                       {
+                               Write((byte)value);
+                       }
+                       else if (value <= 0x3FFF)
+                       {
+                               Write((byte)(0x80 | (value >> 8)));
+                               Write((byte)value);
+                       }
+                       else
+                       {
+                               Write((byte)(0xC0 | (value >> 24)));
+                               Write((byte)(value >> 16));
+                               Write((byte)(value >> 8));
+                               Write((byte)value);
+                       }
+               }
+
+               internal void Write(ByteBuffer bb)
+               {
+                       if (pos + bb.Length > buffer.Length)
+                               Grow(bb.Length);
+                       Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
+                       pos += bb.Length;
+               }
+
+               internal void WriteTo(System.IO.Stream stream)
+               {
+                       stream.Write(buffer, 0, this.Length);
+               }
+
+               internal void Clear()
+               {
+                       pos = 0;
+                       __length = 0;
+               }
+
+               internal void Align(int alignment)
+               {
+                       if (pos + alignment > buffer.Length)
+                               Grow(alignment);
+                       int newpos = (pos + alignment - 1) & ~(alignment - 1);
+                       while (pos < newpos)
+                               buffer[pos++] = 0;
+               }
+
+               internal void WriteTypeDefOrRefEncoded(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case TypeDefTable.Index:
+                                       WriteCompressedInt((token & 0xFFFFFF) << 2 | 0);
+                                       break;
+                               case TypeRefTable.Index:
+                                       WriteCompressedInt((token & 0xFFFFFF) << 2 | 1);
+                                       break;
+                               case TypeSpecTable.Index:
+                                       WriteCompressedInt((token & 0xFFFFFF) << 2 | 2);
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+               }
+
+               internal void Write(System.IO.Stream stream)
+               {
+                       const int chunkSize = 8192;
+                       for (; ; )
+                       {
+                               if (pos + chunkSize > buffer.Length)
+                                       Grow(chunkSize);
+                               int read = stream.Read(buffer, pos, chunkSize);
+                               if (read <= 0)
+                               {
+                                       break;
+                               }
+                               pos += read;
+                       }
+               }
+
+               internal byte[] ToArray()
+               {
+                       byte[] buf = new byte[pos];
+                       Buffer.BlockCopy(buffer, 0, buf, 0, pos);
+                       return buf;
+               }
+
+               internal static ByteBuffer Wrap(byte[] buf)
+               {
+                       return new ByteBuffer(buf, buf.Length);
+               }
+
+               internal static ByteBuffer Wrap(byte[] buf, int length)
+               {
+                       return new ByteBuffer(buf, length);
+               }
+
+               internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
+               {
+                       for (int i = 0; i < len; i++)
+                       {
+                               if (buffer[pos + i] != bb2.buffer[pos2 + i])
+                               {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+
+               internal int Hash()
+               {
+                       int hash = 0;
+                       int len = this.Length;
+                       for (int i = 0; i < len; i++)
+                       {
+                               hash *= 37;
+                               hash ^= buffer[i];
+                       }
+                       return hash;
+               }
+
+               internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset)
+               {
+                       return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset);
+               }
+
+               internal void Patch(int offset, byte b)
+               {
+                       buffer[offset] = b;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/Heaps.cs b/mcs/class/IKVM.Reflection/Writer/Heaps.cs
new file mode 100644 (file)
index 0000000..b8764d2
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+       abstract class Heap
+       {
+               protected bool frozen;
+               protected int unalignedlength;
+
+               internal void Write(MetadataWriter mw)
+               {
+                       int pos = mw.Position;
+                       WriteImpl(mw);
+                       Debug.Assert(mw.Position == pos + unalignedlength);
+                       int align = Length - unalignedlength;
+                       for (int i = 0; i < align; i++)
+                       {
+                               mw.Write((byte)0);
+                       }
+               }
+
+               internal bool IsBig
+               {
+                       get { return Length > 65535; }
+               }
+
+               internal int Length
+               {
+                       get
+                       {
+                               if (!frozen)
+                                       throw new InvalidOperationException();
+                               return (unalignedlength + 3) & ~3;
+                       }
+               }
+
+               protected abstract void WriteImpl(MetadataWriter mw);
+       }
+
+       abstract class SimpleHeap : Heap
+       {
+               internal void Freeze()
+               {
+                       if (frozen)
+                               throw new InvalidOperationException();
+                       frozen = true;
+                       unalignedlength = GetLength();
+               }
+
+               protected abstract int GetLength();
+       }
+
+       sealed class TableHeap : Heap
+       {
+               internal void Freeze(MetadataWriter mw)
+               {
+                       if (frozen)
+                               throw new InvalidOperationException();
+                       frozen = true;
+                       unalignedlength = GetLength(mw);
+               }
+
+               protected override void WriteImpl(MetadataWriter mw)
+               {
+                       Table[] tables = mw.ModuleBuilder.GetTables();
+                       // Header
+                       mw.Write(0);            // Reserved
+                       int ver = mw.ModuleBuilder.MDStreamVersion;
+                       mw.Write((byte)(ver >> 16));    // MajorVersion
+                       mw.Write((byte)ver);                    // MinorVersion
+                       byte heapSizes = 0;
+                       if (mw.ModuleBuilder.Strings.IsBig)
+                       {
+                               heapSizes |= 0x01;
+                       }
+                       if (mw.ModuleBuilder.Guids.IsBig)
+                       {
+                               heapSizes |= 0x02;
+                       }
+                       if (mw.ModuleBuilder.Blobs.IsBig)
+                       {
+                               heapSizes |= 0x04;
+                       }
+                       mw.Write(heapSizes);// HeapSizes
+                       // LAMESPEC spec says reserved, but .NET 2.0 Ref.Emit sets it to 0x10
+                       mw.Write((byte)0x10);   // Reserved
+                       long bit = 1;
+                       long valid = 0;
+                       foreach (Table table in tables)
+                       {
+                               if (table != null && table.RowCount > 0)
+                               {
+                                       valid |= bit;
+                               }
+                               bit <<= 1;
+                       }
+                       mw.Write(valid);        // Valid
+                       mw.Write(0x0016003301FA00L);    // Sorted
+                       // Rows
+                       foreach (Table table in tables)
+                       {
+                               if (table != null && table.RowCount > 0)
+                               {
+                                       mw.Write(table.RowCount);
+                               }
+                       }
+                       // Tables
+                       foreach (Table table in tables)
+                       {
+                               if (table != null && table.RowCount > 0)
+                               {
+                                       int pos = mw.Position;
+                                       table.Write(mw);
+                                       Debug.Assert(mw.Position - pos == table.GetLength(mw));
+                               }
+                       }
+                       // unexplained extra padding
+                       mw.Write((byte)0);
+               }
+
+               private int GetLength(MetadataWriter mw)
+               {
+                       int len = 4 + 4 + 8 + 8;
+                       foreach (Table table in mw.ModuleBuilder.GetTables())
+                       {
+                               if (table != null && table.RowCount > 0)
+                               {
+                                       len += 4;       // row count
+                                       len += table.GetLength(mw);
+                               }
+                       }
+                       // note that we pad one extra (unexplained) byte
+                       return len + 1;
+               }
+       }
+
+       sealed class StringHeap : SimpleHeap
+       {
+               private List<string> list = new List<string>();
+               private Dictionary<string, int> strings = new Dictionary<string, int>();
+               private int nextOffset;
+
+               internal StringHeap()
+               {
+                       Add("");
+               }
+
+               internal int Add(string str)
+               {
+                       Debug.Assert(!frozen);
+                       int offset;
+                       if (!strings.TryGetValue(str, out offset))
+                       {
+                               offset = nextOffset;
+                               nextOffset += System.Text.Encoding.UTF8.GetByteCount(str) + 1;
+                               list.Add(str);
+                               strings.Add(str, offset);
+                       }
+                       return offset;
+               }
+
+               protected override int GetLength()
+               {
+                       return nextOffset;
+               }
+
+               protected override void WriteImpl(MetadataWriter mw)
+               {
+                       foreach (string str in list)
+                       {
+                               mw.Write(System.Text.Encoding.UTF8.GetBytes(str));
+                               mw.Write((byte)0);
+                       }
+               }
+       }
+
+       sealed class UserStringHeap : SimpleHeap
+       {
+               private List<string> list = new List<string>();
+               private Dictionary<string, int> strings = new Dictionary<string, int>();
+               private int nextOffset;
+
+               internal UserStringHeap()
+               {
+                       nextOffset = 1;
+               }
+
+               internal bool IsEmpty
+               {
+                       get { return nextOffset == 1; }
+               }
+
+               internal int Add(string str)
+               {
+                       Debug.Assert(!frozen);
+                       int offset;
+                       if (!strings.TryGetValue(str, out offset))
+                       {
+                               int length = str.Length * 2 + 1 + MetadataWriter.GetCompressedIntLength(str.Length * 2 + 1);
+                               if (nextOffset + length > 0xFFFFFF)
+                               {
+                                       throw new FileFormatLimitationExceededException("No logical space left to create more user strings.", FileFormatLimitationExceededException.META_E_STRINGSPACE_FULL);
+                               }
+                               offset = nextOffset;
+                               nextOffset += length;
+                               list.Add(str);
+                               strings.Add(str, offset);
+                       }
+                       return offset;
+               }
+
+               protected override int GetLength()
+               {
+                       return nextOffset;
+               }
+
+               protected override void WriteImpl(MetadataWriter mw)
+               {
+                       mw.Write((byte)0);
+                       foreach (string str in list)
+                       {
+                               mw.WriteCompressedInt(str.Length * 2 + 1);
+                               byte hasSpecialChars = 0;
+                               foreach (char ch in str)
+                               {
+                                       mw.Write((ushort)ch);
+                                       if (hasSpecialChars == 0 && (ch < 0x20 || ch > 0x7E))
+                                       {
+                                               if (ch > 0x7E
+                                                       || (ch >= 0x01 && ch <= 0x08)
+                                                       || (ch >= 0x0E && ch <= 0x1F)
+                                                       || ch == 0x27
+                                                       || ch == 0x2D)
+                                               {
+                                                       hasSpecialChars = 1;
+                                               }
+                                       }
+                               }
+                               mw.Write(hasSpecialChars);
+                       }
+               }
+       }
+
+       sealed class GuidHeap : SimpleHeap
+       {
+               private List<Guid> list = new List<Guid>();
+
+               internal GuidHeap()
+               {
+               }
+
+               internal int Add(Guid guid)
+               {
+                       Debug.Assert(!frozen);
+                       list.Add(guid);
+                       return list.Count;
+               }
+
+               protected override int GetLength()
+               {
+                       return list.Count * 16;
+               }
+
+               protected override void WriteImpl(MetadataWriter mw)
+               {
+                       foreach (Guid guid in list)
+                       {
+                               mw.Write(guid.ToByteArray());
+                       }
+               }
+       }
+
+       sealed class BlobHeap : SimpleHeap
+       {
+               private Key[] map = new Key[8179];
+               private readonly ByteBuffer buf = new ByteBuffer(32);
+
+               private struct Key
+               {
+                       internal Key[] next;
+                       internal int len;
+                       internal int hash;
+                       internal int offset;
+               }
+
+               internal BlobHeap()
+               {
+                       buf.Write((byte)0);
+               }
+
+               internal int Add(ByteBuffer bb)
+               {
+                       Debug.Assert(!frozen);
+                       if (bb.Length == 0)
+                       {
+                               return 0;
+                       }
+                       int lenlen = MetadataWriter.GetCompressedIntLength(bb.Length);
+                       int hash = bb.Hash();
+                       int index = (hash & 0x7FFFFFFF) % map.Length;
+                       Key[] keys = map;
+                       int last = index;
+                       while (keys[index].offset != 0)
+                       {
+                               if (keys[index].hash == hash
+                                       && keys[index].len == bb.Length
+                                       && buf.Match(keys[index].offset + lenlen, bb, 0, bb.Length))
+                               {
+                                       return keys[index].offset;
+                               }
+                               if (index == last)
+                               {
+                                       if (keys[index].next == null)
+                                       {
+                                               keys[index].next = new Key[4];
+                                               keys = keys[index].next;
+                                               index = 0;
+                                               break;
+                                       }
+                                       keys = keys[index].next;
+                                       index = -1;
+                                       last = keys.Length - 1;
+                               }
+                               index++;
+                       }
+                       int offset = buf.Position;
+                       buf.WriteCompressedInt(bb.Length);
+                       buf.Write(bb);
+                       keys[index].len = bb.Length;
+                       keys[index].hash = hash;
+                       keys[index].offset = offset;
+                       return offset;
+               }
+
+               protected override int GetLength()
+               {
+                       return buf.Position;
+               }
+
+               protected override void WriteImpl(MetadataWriter mw)
+               {
+                       mw.Write(buf);
+               }
+
+               internal bool IsEmpty
+               {
+                       get { return buf.Position == 1; }
+               }
+
+               internal IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+               {
+                       return buf.GetBlob(blobIndex);
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/MetadataWriter.cs b/mcs/class/IKVM.Reflection/Writer/MetadataWriter.cs
new file mode 100644 (file)
index 0000000..1f17b38
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+       sealed class MetadataWriter : MetadataRW
+       {
+               private readonly ModuleBuilder moduleBuilder;
+               private readonly Stream stream;
+               private readonly byte[] buffer = new byte[8];
+
+               internal MetadataWriter(ModuleBuilder module, Stream stream)
+                       : base(module, module.Strings.IsBig, module.Guids.IsBig, module.Blobs.IsBig)
+               {
+                       this.moduleBuilder = module;
+                       this.stream = stream;
+               }
+
+               internal ModuleBuilder ModuleBuilder
+               {
+                       get { return moduleBuilder; }
+               }
+
+               internal int Position
+               {
+                       get { return (int)stream.Position; }
+               }
+
+               internal void Write(ByteBuffer bb)
+               {
+                       bb.WriteTo(stream);
+               }
+
+               internal void Write(byte[] value)
+               {
+                       stream.Write(value, 0, value.Length);
+               }
+
+               internal void Write(byte value)
+               {
+                       stream.WriteByte(value);
+               }
+
+               internal void Write(ushort value)
+               {
+                       Write((short)value);
+               }
+
+               internal void Write(short value)
+               {
+                       buffer[0] = (byte)value;
+                       buffer[1] = (byte)(value >> 8);
+                       stream.Write(buffer, 0, 2);
+               }
+
+               internal void Write(uint value)
+               {
+                       Write((int)value);
+               }
+
+               internal void Write(int value)
+               {
+                       buffer[0] = (byte)value;
+                       buffer[1] = (byte)(value >> 8);
+                       buffer[2] = (byte)(value >> 16);
+                       buffer[3] = (byte)(value >> 24);
+                       stream.Write(buffer, 0, 4);
+               }
+
+               internal void Write(ulong value)
+               {
+                       Write((long)value);
+               }
+
+               internal void Write(long value)
+               {
+                       buffer[0] = (byte)value;
+                       buffer[1] = (byte)(value >> 8);
+                       buffer[2] = (byte)(value >> 16);
+                       buffer[3] = (byte)(value >> 24);
+                       buffer[4] = (byte)(value >> 32);
+                       buffer[5] = (byte)(value >> 40);
+                       buffer[6] = (byte)(value >> 48);
+                       buffer[7] = (byte)(value >> 56);
+                       stream.Write(buffer, 0, 8);
+               }
+
+               internal void WriteCompressedInt(int value)
+               {
+                       if (value <= 0x7F)
+                       {
+                               Write((byte)value);
+                       }
+                       else if (value <= 0x3FFF)
+                       {
+                               Write((byte)(0x80 | (value >> 8)));
+                               Write((byte)value);
+                       }
+                       else
+                       {
+                               Write((byte)(0xC0 | (value >> 24)));
+                               Write((byte)(value >> 16));
+                               Write((byte)(value >> 8));
+                               Write((byte)value);
+                       }
+               }
+
+               internal static int GetCompressedIntLength(int value)
+               {
+                       if (value <= 0x7F)
+                       {
+                               return 1;
+                       }
+                       else if (value <= 0x3FFF)
+                       {
+                               return 2;
+                       }
+                       else
+                       {
+                               return 4;
+                       }
+               }
+
+               internal void WriteStringIndex(int index)
+               {
+                       if (bigStrings)
+                       {
+                               Write(index);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteGuidIndex(int index)
+               {
+                       if (bigGuids)
+                       {
+                               Write(index);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteBlobIndex(int index)
+               {
+                       if (bigBlobs)
+                       {
+                               Write(index);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteTypeDefOrRef(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case 0:
+                                       break;
+                               case TypeDefTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 0;
+                                       break;
+                               case TypeRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 1;
+                                       break;
+                               case TypeSpecTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 2;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigTypeDefOrRef)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteEncodedTypeDefOrRef(int encodedToken)
+               {
+                       if (bigTypeDefOrRef)
+                       {
+                               Write(encodedToken);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+
+               internal void WriteHasCustomAttribute(int encodedToken)
+               {
+                       // NOTE because we've already had to do the encoding (to be able to sort the table)
+                       // here we simple write the value
+                       if (bigHasCustomAttribute)
+                       {
+                               Write(encodedToken);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+
+               internal void WriteCustomAttributeType(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case MethodDefTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 2;
+                                       break;
+                               case MemberRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 3;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigCustomAttributeType)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteField(int index)
+               {
+                       if (bigField)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteMethodDef(int index)
+               {
+                       if (bigMethodDef)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteParam(int index)
+               {
+                       if (bigParam)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteTypeDef(int index)
+               {
+                       if (bigTypeDef)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteEvent(int index)
+               {
+                       if (bigEvent)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteProperty(int index)
+               {
+                       if (bigProperty)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteGenericParam(int index)
+               {
+                       if (bigGenericParam)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteModuleRef(int index)
+               {
+                       if (bigModuleRef)
+                       {
+                               Write(index & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)index);
+                       }
+               }
+
+               internal void WriteResolutionScope(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case ModuleTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 0;
+                                       break;
+                               case ModuleRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 1;
+                                       break;
+                               case AssemblyRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 2;
+                                       break;
+                               case TypeRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 3;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigResolutionScope)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteMemberRefParent(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case TypeDefTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 0;
+                                       break;
+                               case TypeRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 1;
+                                       break;
+                               case ModuleRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 2;
+                                       break;
+                               case MethodDefTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 3;
+                                       break;
+                               case TypeSpecTable.Index:
+                                       token = (token & 0xFFFFFF) << 3 | 4;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigMemberRefParent)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteMethodDefOrRef(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case MethodDefTable.Index:
+                                       token = (token & 0xFFFFFF) << 1 | 0;
+                                       break;
+                               case MemberRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 1 | 1;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigMethodDefOrRef)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteHasConstant(int encodedToken)
+               {
+                       // NOTE because we've already had to do the encoding (to be able to sort the table)
+                       // here we simple write the value
+                       if (bigHasConstant)
+                       {
+                               Write(encodedToken);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+
+               internal void WriteHasSemantics(int encodedToken)
+               {
+                       // NOTE because we've already had to do the encoding (to be able to sort the table)
+                       // here we simple write the value
+                       if (bigHasSemantics)
+                       {
+                               Write(encodedToken);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+
+               internal void WriteImplementation(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case 0:
+                                       break;
+                               case FileTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 0;
+                                       break;
+                               case AssemblyRefTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 1;
+                                       break;
+                               case ExportedTypeTable.Index:
+                                       token = (token & 0xFFFFFF) << 2 | 2;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigImplementation)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteTypeOrMethodDef(int encodedToken)
+               {
+                       // NOTE because we've already had to do the encoding (to be able to sort the table)
+                       // here we simple write the value
+                       if (bigTypeOrMethodDef)
+                       {
+                               Write(encodedToken);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+
+               internal void WriteHasDeclSecurity(int encodedToken)
+               {
+                       // NOTE because we've already had to do the encoding (to be able to sort the table)
+                       // here we simple write the value
+                       if (bigHasDeclSecurity)
+                       {
+                               Write(encodedToken);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+
+               internal void WriteMemberForwarded(int token)
+               {
+                       switch (token >> 24)
+                       {
+                               case FieldTable.Index:
+                                       token = (token & 0xFFFFFF) << 1 | 0;
+                                   break;
+                               case MethodDefTable.Index:
+                                       token = (token & 0xFFFFFF) << 1 | 1;
+                                       break;
+                               default:
+                                       throw new InvalidOperationException();
+                       }
+                       if (bigMemberForwarded)
+                       {
+                               Write(token);
+                       }
+                       else
+                       {
+                               Write((short)token);
+                       }
+               }
+
+               internal void WriteHasFieldMarshal(int encodedToken)
+               {
+                       // NOTE because we've already had to do the encoding (to be able to sort the table)
+                       // here we simple write the value
+                       if (bigHasFieldMarshal)
+                       {
+                               Write(encodedToken & 0xFFFFFF);
+                       }
+                       else
+                       {
+                               Write((short)encodedToken);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/ModuleWriter.cs b/mcs/class/IKVM.Reflection/Writer/ModuleWriter.cs
new file mode 100644 (file)
index 0000000..c4208f8
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Security.Cryptography;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+       static class ModuleWriter
+       {
+               internal static void WriteModule(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder,
+                       PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine,
+                       ResourceSection resources, int entryPointToken)
+               {
+                       moduleBuilder.FixupMethodBodyTokens();
+
+                       moduleBuilder.ModuleTable.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleBuilder.Guids.Add(moduleBuilder.ModuleVersionId), 0, 0);
+
+                       if (moduleBuilder.UserStrings.IsEmpty)
+                       {
+                               // for compat with Ref.Emit, if there aren't any user strings, we add one
+                               moduleBuilder.UserStrings.Add(" ");
+                       }
+
+                       if (resources != null)
+                       {
+                               resources.Finish();
+                       }
+
+                       using (FileStream fs = new FileStream(moduleBuilder.FullyQualifiedName, FileMode.Create))
+                       {
+                               PEWriter writer = new PEWriter(fs);
+                               switch (imageFileMachine)
+                               {
+                                       case ImageFileMachine.I386:
+                                               writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386;
+                                               writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE;
+                                               break;
+                                       case ImageFileMachine.AMD64:
+                                               writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
+                                               writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
+                                               writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
+                                               writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+                                               writer.Headers.OptionalHeader.SizeOfStackReserve = 0x400000;
+                                               writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
+                                               writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
+                                               break;
+                                       case ImageFileMachine.IA64:
+                                               writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64;
+                                               writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
+                                               writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
+                                               writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+                                               writer.Headers.OptionalHeader.SizeOfStackReserve = 0x400000;
+                                               writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
+                                               writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
+                                               break;
+                                       default:
+                                               throw new ArgumentOutOfRangeException("imageFileMachine");
+                               }
+                               if (fileKind == PEFileKinds.Dll)
+                               {
+                                       writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_DLL;
+                               }
+
+                               switch (fileKind)
+                               {
+                                       case PEFileKinds.WindowApplication:
+                                               writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_GUI;
+                                               break;
+                                       default:
+                                               writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_CUI;
+                                               break;
+                               }
+                               writer.Headers.OptionalHeader.DllCharacteristics =
+                                       IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
+                                       IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_NO_SEH |
+                                       IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_NX_COMPAT |
+                                       IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
+
+                               CliHeader cliHeader = new CliHeader();
+                               cliHeader.Cb = 0x48;
+                               cliHeader.MajorRuntimeVersion = 2;
+                               cliHeader.MinorRuntimeVersion = moduleBuilder.MDStreamVersion < 0x20000 ? (ushort)0 : (ushort)5;
+                               if ((portableExecutableKind & PortableExecutableKinds.ILOnly) != 0)
+                               {
+                                       cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_ILONLY;
+                               }
+                               if ((portableExecutableKind & PortableExecutableKinds.Required32Bit) != 0)
+                               {
+                                       cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED;
+                               }
+                               if (keyPair != null)
+                               {
+                                       cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED;
+                               }
+                               if (moduleBuilder.IsPseudoToken(entryPointToken))
+                               {
+                                       entryPointToken = moduleBuilder.ResolvePseudoToken(entryPointToken);
+                               }
+                               cliHeader.EntryPointToken = (uint)entryPointToken;
+
+                               moduleBuilder.Strings.Freeze();
+                               moduleBuilder.UserStrings.Freeze();
+                               moduleBuilder.Guids.Freeze();
+                               moduleBuilder.Blobs.Freeze();
+                               MetadataWriter mw = new MetadataWriter(moduleBuilder, fs);
+                               moduleBuilder.Tables.Freeze(mw);
+                               TextSection code = new TextSection(writer, cliHeader, moduleBuilder, ComputeStrongNameSignatureLength(publicKey));
+
+                               // Import Directory
+                               writer.Headers.OptionalHeader.DataDirectory[1].VirtualAddress = code.ImportDirectoryRVA;
+                               writer.Headers.OptionalHeader.DataDirectory[1].Size = code.ImportDirectoryLength;
+
+                               // Import Address Table Directory
+                               writer.Headers.OptionalHeader.DataDirectory[12].VirtualAddress = code.ImportAddressTableRVA;
+                               writer.Headers.OptionalHeader.DataDirectory[12].Size = code.ImportAddressTableLength;
+
+                               // COM Descriptor Directory
+                               writer.Headers.OptionalHeader.DataDirectory[14].VirtualAddress = code.ComDescriptorRVA;
+                               writer.Headers.OptionalHeader.DataDirectory[14].Size = code.ComDescriptorLength;
+
+                               // Debug Directory
+                               if (code.DebugDirectoryLength != 0)
+                               {
+                                       writer.Headers.OptionalHeader.DataDirectory[6].VirtualAddress = code.DebugDirectoryRVA;
+                                       writer.Headers.OptionalHeader.DataDirectory[6].Size = code.DebugDirectoryLength;
+                               }
+
+                               writer.Headers.FileHeader.NumberOfSections = 2;
+
+                               if (moduleBuilder.initializedData.Length != 0)
+                               {
+                                       writer.Headers.FileHeader.NumberOfSections++;
+                               }
+
+                               if (resources != null && resources.Length != 0)
+                               {
+                                       writer.Headers.FileHeader.NumberOfSections++;
+                               }
+
+                               SectionHeader text = new SectionHeader();
+                               text.Name = ".text";
+                               text.VirtualAddress = code.BaseRVA;
+                               text.VirtualSize = (uint)code.Length;
+                               text.PointerToRawData = code.PointerToRawData;
+                               text.SizeOfRawData = writer.ToFileAlignment((uint)code.Length);
+                               text.Characteristics = SectionHeader.IMAGE_SCN_CNT_CODE | SectionHeader.IMAGE_SCN_MEM_EXECUTE | SectionHeader.IMAGE_SCN_MEM_READ;
+
+                               SectionHeader sdata = new SectionHeader();
+                               sdata.Name = ".sdata";
+                               sdata.VirtualAddress = text.VirtualAddress + writer.ToSectionAlignment(text.VirtualSize);
+                               sdata.VirtualSize = (uint)moduleBuilder.initializedData.Length;
+                               sdata.PointerToRawData = text.PointerToRawData + text.SizeOfRawData;
+                               sdata.SizeOfRawData = writer.ToFileAlignment((uint)moduleBuilder.initializedData.Length);
+                               sdata.Characteristics = SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_MEM_WRITE;
+
+                               SectionHeader rsrc = new SectionHeader();
+                               rsrc.Name = ".rsrc";
+                               rsrc.VirtualAddress = sdata.VirtualAddress + writer.ToSectionAlignment(sdata.VirtualSize);
+                               rsrc.PointerToRawData = sdata.PointerToRawData + sdata.SizeOfRawData;
+                               rsrc.VirtualSize = resources == null ? 0 : (uint)resources.Length;
+                               rsrc.SizeOfRawData = writer.ToFileAlignment(rsrc.VirtualSize);
+                               rsrc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA;
+
+                               if (rsrc.SizeOfRawData != 0)
+                               {
+                                       // Resource Directory
+                                       writer.Headers.OptionalHeader.DataDirectory[2].VirtualAddress = rsrc.VirtualAddress;
+                                       writer.Headers.OptionalHeader.DataDirectory[2].Size = rsrc.VirtualSize;
+                               }
+
+                               SectionHeader reloc = new SectionHeader();
+                               reloc.Name = ".reloc";
+                               reloc.VirtualAddress = rsrc.VirtualAddress + writer.ToSectionAlignment(rsrc.VirtualSize);
+                               reloc.VirtualSize = 12;
+                               reloc.PointerToRawData = rsrc.PointerToRawData + rsrc.SizeOfRawData;
+                               reloc.SizeOfRawData = writer.ToFileAlignment(reloc.VirtualSize);
+                               reloc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_DISCARDABLE;
+
+                               // Base Relocation Directory
+                               writer.Headers.OptionalHeader.DataDirectory[5].VirtualAddress = reloc.VirtualAddress;
+                               writer.Headers.OptionalHeader.DataDirectory[5].Size = reloc.VirtualSize;
+
+                               writer.Headers.OptionalHeader.SizeOfCode = text.SizeOfRawData;
+                               writer.Headers.OptionalHeader.SizeOfInitializedData = sdata.SizeOfRawData + rsrc.SizeOfRawData + reloc.SizeOfRawData;
+                               writer.Headers.OptionalHeader.SizeOfUninitializedData = 0;
+                               writer.Headers.OptionalHeader.SizeOfImage = reloc.VirtualAddress + writer.ToSectionAlignment(reloc.VirtualSize);
+                               writer.Headers.OptionalHeader.SizeOfHeaders = text.PointerToRawData;
+                               writer.Headers.OptionalHeader.BaseOfCode = code.BaseRVA;
+                               writer.Headers.OptionalHeader.BaseOfData = sdata.VirtualAddress;
+                               writer.Headers.OptionalHeader.ImageBase = (ulong)moduleBuilder.__ImageBase;
+
+                               if (imageFileMachine == ImageFileMachine.IA64)
+                               {
+                                       // apparently for IA64 AddressOfEntryPoint points to the address of the entry point
+                                       // (i.e. there is an additional layer of indirection), so we add the offset to the pointer
+                                       writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + 0x20;
+                               }
+                               else
+                               {
+                                       writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA;
+                               }
+
+                               writer.WritePEHeaders();
+                               writer.WriteSectionHeader(text);
+                               if (sdata.SizeOfRawData != 0)
+                               {
+                                       writer.WriteSectionHeader(sdata);
+                               }
+                               if (rsrc.SizeOfRawData != 0)
+                               {
+                                       writer.WriteSectionHeader(rsrc);
+                               }
+                               writer.WriteSectionHeader(reloc);
+
+                               fs.Seek(text.PointerToRawData, SeekOrigin.Begin);
+                               code.Write(mw, (int)sdata.VirtualAddress);
+
+                               fs.Seek(sdata.PointerToRawData, SeekOrigin.Begin);
+                               mw.Write(moduleBuilder.initializedData);
+
+                               if (rsrc.SizeOfRawData != 0)
+                               {
+                                       fs.Seek(rsrc.PointerToRawData, SeekOrigin.Begin);
+                                       resources.Write(mw, rsrc.VirtualAddress);
+                               }
+
+                               fs.Seek(reloc.PointerToRawData, SeekOrigin.Begin);
+                               // .reloc section
+                               uint relocAddress = code.StartupStubRVA;
+                               switch (imageFileMachine)
+                               {
+                                       case ImageFileMachine.I386:
+                                       case ImageFileMachine.AMD64:
+                                               relocAddress += 2;
+                                               break;
+                                       case ImageFileMachine.IA64:
+                                               relocAddress += 0x20;
+                                               break;
+                               }
+                               uint pageRVA = relocAddress & ~0xFFFU;
+                               mw.Write(pageRVA);      // PageRVA
+                               mw.Write(0x000C);       // Block Size
+                               if (imageFileMachine == ImageFileMachine.I386)
+                               {
+                                       mw.Write(0x3000 + relocAddress - pageRVA);                              // Type / Offset
+                               }
+                               else if (imageFileMachine == ImageFileMachine.AMD64)
+                               {
+                                       mw.Write(0xA000 + relocAddress - pageRVA);                              // Type / Offset
+                               }
+                               else if (imageFileMachine == ImageFileMachine.IA64)
+                               {
+                                       // on IA64 the StartupStubRVA is 16 byte aligned, so these two addresses won't cross a page boundary
+                                       mw.Write((short)(0xA000 + relocAddress - pageRVA));             // Type / Offset
+                                       mw.Write((short)(0xA000 + relocAddress - pageRVA + 8)); // Type / Offset
+                               }
+
+                               // file alignment
+                               mw.Write(new byte[writer.Headers.OptionalHeader.FileAlignment - reloc.VirtualSize]);
+
+                               // do the strong naming
+                               if (keyPair != null)
+                               {
+                                       StrongName(fs, keyPair, writer.HeaderSize, text.PointerToRawData, code.StrongNameSignatureRVA - text.VirtualAddress + text.PointerToRawData, code.StrongNameSignatureLength);
+                               }
+                       }
+
+                       if (moduleBuilder.symbolWriter != null)
+                       {
+                               moduleBuilder.WriteSymbolTokenMap();
+                               moduleBuilder.symbolWriter.Close();
+                       }
+               }
+
+               private static int ComputeStrongNameSignatureLength(byte[] publicKey)
+               {
+                       if (publicKey == null)
+                       {
+                               return 0;
+                       }
+                       else if (publicKey.Length == 16)
+                       {
+                               // it must be the ECMA pseudo public key, we don't know the key size of the real key, but currently both Mono and Microsoft use a 1024 bit key size
+                               return 128;
+                       }
+                       else
+                       {
+                               // for the supported strong naming algorithms, the signature size is the same as the key size
+                               // (we have to subtract 32 for the header)
+                               return publicKey.Length - 32;
+                       }
+               }
+
+               private static void StrongName(FileStream fs, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength)
+               {
+                       SHA1Managed hash = new SHA1Managed();
+                       using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
+                       {
+                               fs.Seek(0, SeekOrigin.Begin);
+                               byte[] buf = new byte[8192];
+                               HashChunk(fs, cs, buf, (int)headerLength);
+                               fs.Seek(textSectionFileOffset, SeekOrigin.Begin);
+                               HashChunk(fs, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset));
+                               fs.Seek(strongNameSignatureLength, SeekOrigin.Current);
+                               HashChunk(fs, cs, buf, (int)(fs.Length - (strongNameSignatureFileOffset + strongNameSignatureLength)));
+                       }
+                       using (RSA rsa = CryptoHack.CreateRSA(keyPair))
+                       {
+                               RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa);
+                               byte[] signature = sign.CreateSignature(hash);
+                               Array.Reverse(signature);
+                               if (signature.Length != strongNameSignatureLength)
+                               {
+                                       throw new InvalidOperationException("Signature length mismatch");
+                               }
+                               fs.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin);
+                               fs.Write(signature, 0, signature.Length);
+                       }
+
+                       // compute the PE checksum
+                       fs.Seek(0, SeekOrigin.Begin);
+                       int count = (int)fs.Length / 4;
+                       BinaryReader br = new BinaryReader(fs);
+                       long sum = 0;
+                       for (int i = 0; i < count; i++)
+                       {
+                               sum += br.ReadUInt32();
+                               int carry = (int)(sum >> 32);
+                               sum &= 0xFFFFFFFFU;
+                               sum += carry;
+                       }
+                       while ((sum >> 16) != 0)
+                       {
+                               sum = (sum & 0xFFFF) + (sum >> 16);
+                       }
+                       sum += fs.Length;
+
+                       // write the PE checksum, note that it is always at offset 0xD8 in the file
+                       ByteBuffer bb = new ByteBuffer(4);
+                       bb.Write((int)sum);
+                       fs.Seek(0xD8, SeekOrigin.Begin);
+                       bb.WriteTo(fs);
+               }
+
+               internal static void HashChunk(FileStream fs, CryptoStream cs, byte[] buf, int length)
+               {
+                       while (length > 0)
+                       {
+                               int read = fs.Read(buf, 0, Math.Min(buf.Length, length));
+                               cs.Write(buf, 0, read);
+                               length -= read;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/PEWriter.cs b/mcs/class/IKVM.Reflection/Writer/PEWriter.cs
new file mode 100644 (file)
index 0000000..3ddd20b
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.IO;
+using BYTE = System.Byte;
+using WORD = System.UInt16;
+using DWORD = System.UInt32;
+using ULONGLONG = System.UInt64;
+
+namespace IKVM.Reflection.Writer
+{
+       sealed class PEWriter
+       {
+               private readonly BinaryWriter bw;
+               private readonly IMAGE_NT_HEADERS hdr = new IMAGE_NT_HEADERS();
+
+               internal PEWriter(Stream stream)
+               {
+                       bw = new BinaryWriter(stream);
+                       WriteMSDOSHeader();
+               }
+
+               public IMAGE_NT_HEADERS Headers
+               {
+                       get { return hdr; }
+               }
+
+               public uint HeaderSize
+               {
+                       get
+                       {
+                               return (uint)
+                                       ((8 * 16) +     // MSDOS header
+                                       4 +                             // signature
+                                       20 +                    // IMAGE_FILE_HEADER
+                                       hdr.FileHeader.SizeOfOptionalHeader +
+                                       hdr.FileHeader.NumberOfSections * 40);
+                       }
+               }
+
+               private void WriteMSDOSHeader()
+               {
+                       bw.Write(new byte[] {
+                               0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
+                               0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+                               0xB8, 0x00, 0x00, 0x00, 0x00, 0x00,     0x00, 0x00,
+                               0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+                               0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
+                               0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68,
+                               0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72,
+                               0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F,
+                               0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E,
+                               0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20,
+                               0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A,
+                               0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+                       });
+               }
+
+               internal void WritePEHeaders()
+               {
+                       bw.Write(hdr.Signature);
+
+                       // IMAGE_FILE_HEADER
+                       bw.Write(hdr.FileHeader.Machine);
+                       bw.Write(hdr.FileHeader.NumberOfSections);
+                       bw.Write(hdr.FileHeader.TimeDateStamp);
+                       bw.Write(hdr.FileHeader.PointerToSymbolTable);
+                       bw.Write(hdr.FileHeader.NumberOfSymbols);
+                       bw.Write(hdr.FileHeader.SizeOfOptionalHeader);
+                       bw.Write(hdr.FileHeader.Characteristics);
+
+                       // IMAGE_OPTIONAL_HEADER
+                       hdr.OptionalHeader.Write(bw);
+               }
+
+               internal void WriteSectionHeader(SectionHeader sectionHeader)
+               {
+                       byte[] name = new byte[8];
+                       System.Text.Encoding.UTF8.GetBytes(sectionHeader.Name, 0, sectionHeader.Name.Length, name, 0);
+                       bw.Write(name);
+                       bw.Write(sectionHeader.VirtualSize);
+                       bw.Write(sectionHeader.VirtualAddress);
+                       bw.Write(sectionHeader.SizeOfRawData);
+                       bw.Write(sectionHeader.PointerToRawData);
+                       bw.Write(sectionHeader.PointerToRelocations);
+                       bw.Write(sectionHeader.PointerToLinenumbers);
+                       bw.Write(sectionHeader.NumberOfRelocations);
+                       bw.Write(sectionHeader.NumberOfLinenumbers);
+                       bw.Write(sectionHeader.Characteristics);
+               }
+
+               internal uint ToFileAlignment(uint p)
+               {
+                       return (p + (Headers.OptionalHeader.FileAlignment - 1)) & ~(Headers.OptionalHeader.FileAlignment - 1);
+               }
+
+               internal uint ToSectionAlignment(uint p)
+               {
+                       return (p + (Headers.OptionalHeader.SectionAlignment - 1)) & ~(Headers.OptionalHeader.SectionAlignment - 1);
+               }
+       }
+
+       sealed class IMAGE_NT_HEADERS
+       {
+               public DWORD Signature = 0x00004550;    // "PE\0\0"
+               public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
+               public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
+       }
+
+       sealed class IMAGE_FILE_HEADER
+       {
+               public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
+               public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
+               public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
+
+               public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
+               public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
+               public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
+               public const WORD IMAGE_FILE_DLL = 0x2000;
+
+               public WORD Machine;
+               public WORD NumberOfSections;
+               public DWORD TimeDateStamp = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
+               public DWORD PointerToSymbolTable = 0;
+               public DWORD NumberOfSymbols = 0;
+               public WORD SizeOfOptionalHeader = 0xE0;
+               public WORD Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
+       }
+
+       sealed class IMAGE_OPTIONAL_HEADER
+       {
+               public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
+               public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
+
+               public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
+               public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
+
+               public const WORD IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040;
+               public const WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100;
+               public const WORD IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400;
+               public const WORD IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000;
+
+               public WORD Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+               public BYTE MajorLinkerVersion = 8;
+               public BYTE MinorLinkerVersion = 0;
+               public DWORD SizeOfCode;
+               public DWORD SizeOfInitializedData;
+               public DWORD SizeOfUninitializedData;
+               public DWORD AddressOfEntryPoint;
+               public DWORD BaseOfCode;
+               public DWORD BaseOfData;
+               public ULONGLONG ImageBase;
+               public DWORD SectionAlignment = 0x2000;
+               public DWORD FileAlignment = 0x200;
+               public WORD MajorOperatingSystemVersion = 4;
+               public WORD MinorOperatingSystemVersion = 0;
+               public WORD MajorImageVersion = 0;
+               public WORD MinorImageVersion = 0;
+               public WORD MajorSubsystemVersion = 4;
+               public WORD MinorSubsystemVersion = 0;
+               public DWORD Win32VersionValue = 0;
+               public DWORD SizeOfImage;
+               public DWORD SizeOfHeaders;
+               public DWORD CheckSum = 0;
+               public WORD Subsystem;
+               public WORD DllCharacteristics;
+               public ULONGLONG SizeOfStackReserve = 0x100000;
+               public ULONGLONG SizeOfStackCommit = 0x1000;
+               public ULONGLONG SizeOfHeapReserve = 0x100000;
+               public ULONGLONG SizeOfHeapCommit = 0x1000;
+               public DWORD LoaderFlags = 0;
+               public DWORD NumberOfRvaAndSizes = 16;
+               public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
+
+               internal void Write(BinaryWriter bw)
+               {
+                       bw.Write(Magic);
+                       bw.Write(MajorLinkerVersion);
+                       bw.Write(MinorLinkerVersion);
+                       bw.Write(SizeOfCode);
+                       bw.Write(SizeOfInitializedData);
+                       bw.Write(SizeOfUninitializedData);
+                       bw.Write(AddressOfEntryPoint);
+                       bw.Write(BaseOfCode);
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               bw.Write(BaseOfData);
+                               bw.Write((DWORD)ImageBase);
+                       }
+                       else
+                       {
+                               bw.Write(ImageBase);
+                       }
+                       bw.Write(SectionAlignment);
+                       bw.Write(FileAlignment);
+                       bw.Write(MajorOperatingSystemVersion);
+                       bw.Write(MinorOperatingSystemVersion);
+                       bw.Write(MajorImageVersion);
+                       bw.Write(MinorImageVersion);
+                       bw.Write(MajorSubsystemVersion);
+                       bw.Write(MinorSubsystemVersion);
+                       bw.Write(Win32VersionValue);
+                       bw.Write(SizeOfImage);
+                       bw.Write(SizeOfHeaders);
+                       bw.Write(CheckSum);
+                       bw.Write(Subsystem);
+                       bw.Write(DllCharacteristics);
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               bw.Write((DWORD)SizeOfStackReserve);
+                       }
+                       else
+                       {
+                               bw.Write(SizeOfStackReserve);
+                       }
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               bw.Write((DWORD)SizeOfStackCommit);
+                       }
+                       else
+                       {
+                               bw.Write(SizeOfStackCommit);
+                       }
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               bw.Write((DWORD)SizeOfHeapReserve);
+                       }
+                       else
+                       {
+                               bw.Write(SizeOfHeapReserve);
+                       }
+                       if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+                       {
+                               bw.Write((DWORD)SizeOfHeapCommit);
+                       }
+                       else
+                       {
+                               bw.Write(SizeOfHeapCommit);
+                       }
+                       bw.Write(LoaderFlags);
+                       bw.Write(NumberOfRvaAndSizes);
+                       for (int i = 0; i < DataDirectory.Length; i++)
+                       {
+                               bw.Write(DataDirectory[i].VirtualAddress);
+                               bw.Write(DataDirectory[i].Size);
+                       }
+               }
+       }
+
+       struct IMAGE_DATA_DIRECTORY
+       {
+               public DWORD VirtualAddress;
+               public DWORD Size;
+       }
+
+       class SectionHeader
+       {
+               public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
+               public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
+               public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
+               public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
+               public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
+               public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
+
+               public string Name;             // 8 byte UTF8 encoded 0-padded
+               public DWORD VirtualSize;
+               public DWORD VirtualAddress;
+               public DWORD SizeOfRawData;
+               public DWORD PointerToRawData;
+#pragma warning disable 649 // the follow fields are never assigned to
+               public DWORD PointerToRelocations;
+               public DWORD PointerToLinenumbers;
+               public WORD NumberOfRelocations;
+               public WORD NumberOfLinenumbers;
+#pragma warning restore 649
+               public DWORD Characteristics;
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/ResourceSection.cs b/mcs/class/IKVM.Reflection/Writer/ResourceSection.cs
new file mode 100644 (file)
index 0000000..81941e2
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+  Copyright (C) 2010 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection.Writer
+{
+       sealed class ResourceSection
+       {
+               private const int RT_ICON = 3;
+               private const int RT_GROUP_ICON = 14;
+               private const int RT_VERSION = 16;
+               private ResourceDirectoryEntry root = new ResourceDirectoryEntry(new OrdinalOrName("root"));
+               private ByteBuffer bb;
+               private List<int> linkOffsets;
+
+               internal void AddVersionInfo(ByteBuffer versionInfo)
+               {
+                       root[new OrdinalOrName(RT_VERSION)][new OrdinalOrName(1)][new OrdinalOrName(0)].Data = versionInfo;
+               }
+
+               internal void AddIcon(byte[] iconFile)
+               {
+                       BinaryReader br = new BinaryReader(new MemoryStream(iconFile));
+                       ushort idReserved = br.ReadUInt16();
+                       ushort idType = br.ReadUInt16();
+                       ushort idCount = br.ReadUInt16();
+                       if (idReserved != 0 || idType != 1)
+                       {
+                               throw new ArgumentException("The supplied byte array is not a valid .ico file.");
+                       }
+                       ByteBuffer group = new ByteBuffer(6 + 14 * idCount);
+                       group.Write(idReserved);
+                       group.Write(idType);
+                       group.Write(idCount);
+                       for (int i = 0; i < idCount; i++)
+                       {
+                               byte bWidth = br.ReadByte();
+                               byte bHeight = br.ReadByte();
+                               byte bColorCount = br.ReadByte();
+                               byte bReserved = br.ReadByte();
+                               ushort wPlanes = br.ReadUInt16();
+                               ushort wBitCount = br.ReadUInt16();
+                               uint dwBytesInRes = br.ReadUInt32();
+                               uint dwImageOffset = br.ReadUInt32();
+
+                               // we start the icon IDs at 2
+                               ushort id = (ushort)(2 + i);
+
+                               group.Write(bWidth);
+                               group.Write(bHeight);
+                               group.Write(bColorCount);
+                               group.Write(bReserved);
+                               group.Write(wPlanes);
+                               group.Write(wBitCount);
+                               group.Write(dwBytesInRes);
+                               group.Write(id);
+
+                               byte[] icon = new byte[dwBytesInRes];
+                               Buffer.BlockCopy(iconFile, (int)dwImageOffset, icon, 0, icon.Length);
+                               root[new OrdinalOrName(RT_ICON)][new OrdinalOrName(id)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(icon);
+                       }
+                       root[new OrdinalOrName(RT_GROUP_ICON)][new OrdinalOrName(32512)][new OrdinalOrName(0)].Data = group;
+               }
+
+               internal void ExtractResources(byte[] buf)
+               {
+                       ByteReader br = new ByteReader(buf, 0, buf.Length);
+                       while (br.Length >= 32)
+                       {
+                               br.Align(4);
+                               RESOURCEHEADER hdr = new RESOURCEHEADER(br);
+                               if (hdr.DataSize != 0)
+                               {
+                                       root[hdr.TYPE][hdr.NAME][new OrdinalOrName(hdr.LanguageId)].Data = ByteBuffer.Wrap(br.ReadBytes(hdr.DataSize));
+                               }
+                       }
+               }
+
+               internal void Finish()
+               {
+                       if (bb != null)
+                       {
+                               throw new InvalidOperationException();
+                       }
+                       bb = new ByteBuffer(1024);
+                       linkOffsets = new List<int>();
+                       root.Write(bb, linkOffsets);
+                       root = null;
+               }
+
+               internal int Length
+               {
+                       get { return bb.Length; }
+               }
+
+               internal void Write(MetadataWriter mw, uint rva)
+               {
+                       foreach (int offset in linkOffsets)
+                       {
+                               bb.Position = offset;
+                               bb.Write(bb.GetInt32AtCurrentPosition() + (int)rva);
+                       }
+                       mw.Write(bb);
+               }
+       }
+
+       sealed class ResourceDirectoryEntry
+       {
+               internal readonly OrdinalOrName OrdinalOrName;
+               internal ByteBuffer Data;
+               private int namedEntries;
+               private readonly List<ResourceDirectoryEntry> entries = new List<ResourceDirectoryEntry>();
+
+               internal ResourceDirectoryEntry(OrdinalOrName id)
+               {
+                       this.OrdinalOrName = id;
+               }
+
+               internal ResourceDirectoryEntry this[OrdinalOrName id]
+               {
+                       get
+                       {
+                               foreach (ResourceDirectoryEntry entry in entries)
+                               {
+                                       if (entry.OrdinalOrName.Ordinal == id.Ordinal && entry.OrdinalOrName.Name == id.Name)
+                                       {
+                                               return entry;
+                                       }
+                               }
+                               ResourceDirectoryEntry newEntry = new ResourceDirectoryEntry(id);
+                               if (id.Name == null)
+                               {
+                                       entries.Add(newEntry);
+                               }
+                               else
+                               {
+                                       entries.Insert(namedEntries++, newEntry);
+                               }
+                               return newEntry;
+                       }
+               }
+
+               private int DirectoryLength
+               {
+                       get
+                       {
+                               if (Data != null)
+                               {
+                                       return 16;
+                               }
+                               else
+                               {
+                                       int length = 16 + entries.Count * 8;
+                                       foreach (ResourceDirectoryEntry entry in entries)
+                                       {
+                                               length += entry.DirectoryLength;
+                                       }
+                                       return length;
+                               }
+                       }
+               }
+
+               internal void Write(ByteBuffer bb, List<int> linkOffsets)
+               {
+                       if (entries.Count != 0)
+                       {
+                               int stringTableOffset = this.DirectoryLength;
+                               Dictionary<string, int> strings = new Dictionary<string, int>();
+                               ByteBuffer stringTable = new ByteBuffer(16);
+                               int offset = 16 + entries.Count * 8;
+                               for (int pass = 0; pass < 3; pass++)
+                               {
+                                       Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable);
+                               }
+                               // the pecoff spec says that the string table is between the directory entries and the data entries,
+                               // but the windows linker puts them after the data entries, so we do too.
+                               stringTable.Align(4);
+                               offset += stringTable.Length;
+                               WriteResourceDataEntries(bb, linkOffsets, ref offset);
+                               bb.Write(stringTable);
+                               WriteData(bb);
+                       }
+               }
+
+               private void WriteResourceDataEntries(ByteBuffer bb, List<int> linkOffsets, ref int offset)
+               {
+                       foreach (ResourceDirectoryEntry entry in entries)
+                       {
+                               if (entry.Data != null)
+                               {
+                                       linkOffsets.Add(bb.Position);
+                                       bb.Write(offset);
+                                       bb.Write(entry.Data.Length);
+                                       bb.Write(0);    // code page
+                                       bb.Write(0);    // reserved
+                                       offset += (entry.Data.Length + 3) & ~3;
+                               }
+                               else
+                               {
+                                       entry.WriteResourceDataEntries(bb, linkOffsets, ref offset);
+                               }
+                       }
+               }
+
+               private void WriteData(ByteBuffer bb)
+               {
+                       foreach (ResourceDirectoryEntry entry in entries)
+                       {
+                               if (entry.Data != null)
+                               {
+                                       bb.Write(entry.Data);
+                                       bb.Align(4);
+                               }
+                               else
+                               {
+                                       entry.WriteData(bb);
+                               }
+                       }
+               }
+
+               private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
+               {
+                       if (currentDepth == writeDepth)
+                       {
+                               // directory header
+                               bb.Write(0);    // Characteristics
+                               bb.Write(0);    // Time/Date Stamp
+                               bb.Write(0);    // Version (Major / Minor)
+                               bb.Write((ushort)namedEntries);
+                               bb.Write((ushort)(entries.Count - namedEntries));
+                       }
+                       foreach (ResourceDirectoryEntry entry in entries)
+                       {
+                               if (currentDepth == writeDepth)
+                               {
+                                       entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable);
+                               }
+                               else
+                               {
+                                       entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable);
+                               }
+                       }
+               }
+
+               private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
+               {
+                       WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable);
+                       if (Data == null)
+                       {
+                               bb.Write(0x80000000U | (uint)offset);
+                       }
+                       else
+                       {
+                               bb.Write(offset);
+                       }
+                       offset += 16 + entries.Count * 8;
+               }
+
+               private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
+               {
+                       if (id.Name == null)
+                       {
+                               bb.Write((int)id.Ordinal);
+                       }
+                       else
+                       {
+                               int stringOffset;
+                               if (!strings.TryGetValue(id.Name, out stringOffset))
+                               {
+                                       stringOffset = stringTableOffset;
+                                       strings.Add(id.Name, stringOffset);
+                                       stringTableOffset += id.Name.Length * 2 + 2;
+                                       stringTable.Write((ushort)id.Name.Length);
+                                       foreach (char c in id.Name)
+                                       {
+                                               stringTable.Write((short)c);
+                                       }
+                               }
+                               bb.Write(0x80000000U | (uint)stringOffset);
+                       }
+               }
+       }
+
+       struct OrdinalOrName
+       {
+               internal readonly ushort Ordinal;
+               internal readonly string Name;
+
+               internal OrdinalOrName(ushort value)
+               {
+                       Ordinal = value;
+                       Name = null;
+               }
+
+               internal OrdinalOrName(string value)
+               {
+                       Ordinal = 0xFFFF;
+                       Name = value;
+               }
+       }
+
+       struct RESOURCEHEADER
+       {
+               internal int DataSize;
+               internal int HeaderSize;
+               internal OrdinalOrName TYPE;
+               internal OrdinalOrName NAME;
+               internal int DataVersion;
+               internal ushort MemoryFlags;
+               internal ushort LanguageId;
+               internal int Version;
+               internal int Characteristics;
+
+               internal RESOURCEHEADER(ByteReader br)
+               {
+                       DataSize = br.ReadInt32();
+                       HeaderSize = br.ReadInt32();
+                       TYPE = ReadOrdinalOrName(br);
+                       NAME = ReadOrdinalOrName(br);
+                       br.Align(4);
+                       DataVersion = br.ReadInt32();
+                       MemoryFlags = br.ReadUInt16();
+                       LanguageId = br.ReadUInt16();
+                       Version = br.ReadInt32();
+                       Characteristics = br.ReadInt32();
+               }
+
+               private static OrdinalOrName ReadOrdinalOrName(ByteReader br)
+               {
+                       char c = br.ReadChar();
+                       if (c == 0xFFFF)
+                       {
+                               return new OrdinalOrName(br.ReadUInt16());
+                       }
+                       else
+                       {
+                               StringBuilder sb = new StringBuilder();
+                               while (c != 0)
+                               {
+                                       sb.Append(c);
+                                       c = br.ReadChar();
+                               }
+                               return new OrdinalOrName(sb.ToString());
+                       }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/TextSection.cs b/mcs/class/IKVM.Reflection/Writer/TextSection.cs
new file mode 100644 (file)
index 0000000..9b4a7ee
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+       sealed class TextSection
+       {
+               private readonly PEWriter peWriter;
+               private readonly CliHeader cliHeader;
+               private readonly ModuleBuilder moduleBuilder;
+               private readonly uint strongNameSignatureLength;
+
+               internal TextSection(PEWriter peWriter, CliHeader cliHeader, ModuleBuilder moduleBuilder, int strongNameSignatureLength)
+               {
+                       this.peWriter = peWriter;
+                       this.cliHeader = cliHeader;
+                       this.moduleBuilder = moduleBuilder;
+                       this.strongNameSignatureLength = (uint)strongNameSignatureLength;
+               }
+
+               internal uint PointerToRawData
+               {
+                       get { return peWriter.ToFileAlignment(peWriter.HeaderSize); }
+               }
+
+               internal uint BaseRVA
+               {
+                       get { return 0x2000; }
+               }
+
+               internal uint ImportAddressTableRVA
+               {
+                       get { return BaseRVA; }
+               }
+
+               internal uint ImportAddressTableLength
+               {
+                       get
+                       {
+                               if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+                               {
+                                       return 8;
+                               }
+                               else
+                               {
+                                       return 16;
+                               }
+                       }
+               }
+
+               internal uint ComDescriptorRVA
+               {
+                       get { return ImportAddressTableRVA + ImportAddressTableLength; }
+               }
+
+               internal uint ComDescriptorLength
+               {
+                       get { return cliHeader.Cb; }
+               }
+
+               internal uint MethodBodiesRVA
+               {
+                       get { return (ComDescriptorRVA + ComDescriptorLength + 7) & ~7U; }
+               }
+
+               private uint MethodBodiesLength
+               {
+                       get { return (uint)moduleBuilder.methodBodies.Length; }
+               }
+
+               private uint ResourcesRVA
+               {
+                       get
+                       {
+                               if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+                               {
+                                       return (MethodBodiesRVA + MethodBodiesLength + 3) & ~3U;
+                               }
+                               else
+                               {
+                                       return (MethodBodiesRVA + MethodBodiesLength + 15) & ~15U;
+                               }
+                       }
+               }
+
+               private uint ResourcesLength
+               {
+                       get { return (uint)moduleBuilder.manifestResources.Length; }
+               }
+
+               internal uint StrongNameSignatureRVA
+               {
+                       get
+                       {
+                               return (ResourcesRVA + ResourcesLength + 3) & ~3U;
+                       }
+               }
+
+               internal uint StrongNameSignatureLength
+               {
+                       get
+                       {
+                               return strongNameSignatureLength;
+                       }
+               }
+
+               private uint MetadataRVA
+               {
+                       get
+                       {
+                               return (StrongNameSignatureRVA + StrongNameSignatureLength + 3) & ~3U;
+                       }
+               }
+
+               private uint MetadataLength
+               {
+                       get { return (uint)moduleBuilder.MetadataLength; }
+               }
+
+               internal uint DebugDirectoryRVA
+               {
+                       get { return MetadataRVA + MetadataLength; }
+               }
+
+               internal uint DebugDirectoryLength
+               {
+                       get
+                       {
+                               if (DebugDirectoryContentsLength != 0)
+                               {
+                                       return 28;
+                               }
+                               return 0;
+                       }
+               }
+
+               private uint DebugDirectoryContentsLength
+               {
+                       get
+                       {
+                               if (moduleBuilder.symbolWriter != null)
+                               {
+                                       IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
+                                       return (uint)SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd).Length;
+                               }
+                               return 0;
+                       }
+               }
+
+               internal uint ImportDirectoryRVA
+               {
+                       // on AMD64 (and probably IA64) the import directory needs to be 16 byte aligned (on I386 4 byte alignment is sufficient)
+                       get { return (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength + 15) & ~15U; }
+               }
+
+               internal uint ImportDirectoryLength
+               {
+                       get { return (ImportHintNameTableRVA - ImportDirectoryRVA) + 27; }
+               }
+
+               private uint ImportHintNameTableRVA
+               {
+                       get
+                       {
+                               if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+                               {
+                                       return (ImportDirectoryRVA + 48 + 15) & ~15U;
+                               }
+                               else
+                               {
+                                       return (ImportDirectoryRVA + 48 + 4 + 15) & ~15U;
+                               }
+                       }
+               }
+
+               internal uint StartupStubRVA
+               {
+                       get
+                       {
+                               if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
+                               {
+                                       // note that the alignment is driven by the requirement that the two relocation fixups are in a single page
+                                       return (ImportDirectoryRVA + ImportDirectoryLength + 15U) & ~15U;
+                               }
+                               else
+                               {
+                                       // the additional 2 bytes padding are to align the address in the jump (which is a relocation fixup)
+                                       return 2 + ((ImportDirectoryRVA + ImportDirectoryLength + 3U) & ~3U);
+                               }
+                       }
+               }
+
+               internal uint StartupStubLength
+               {
+                       get
+                       {
+                               if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64)
+                               {
+                                       return 12;
+                               }
+                               else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
+                               {
+                                       return 48;
+                               }
+                               else
+                               {
+                                       return 6;
+                               }
+                       }
+               }
+
+               private void WriteRVA(MetadataWriter mw, uint rva)
+               {
+                       if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+                       {
+                               mw.Write(rva);
+                       }
+                       else
+                       {
+                               mw.Write((ulong)rva);
+                       }
+               }
+
+               internal void Write(MetadataWriter mw, int sdataRVA)
+               {
+                       // Now that we're ready to start writing, we need to do some fix ups
+                       moduleBuilder.MethodDef.Fixup(this);
+                       moduleBuilder.MethodImpl.Fixup(moduleBuilder);
+                       moduleBuilder.MethodSemantics.Fixup(moduleBuilder);
+                       moduleBuilder.InterfaceImpl.Fixup();
+                       moduleBuilder.MemberRef.Fixup(moduleBuilder);
+                       moduleBuilder.Constant.Fixup(moduleBuilder);
+                       moduleBuilder.FieldMarshal.Fixup(moduleBuilder);
+                       moduleBuilder.DeclSecurity.Fixup(moduleBuilder);
+                       moduleBuilder.GenericParam.Fixup(moduleBuilder);
+                       moduleBuilder.CustomAttribute.Fixup(moduleBuilder);
+                       moduleBuilder.FieldLayout.Fixup(moduleBuilder);
+                       moduleBuilder.FieldRVA.Fixup(moduleBuilder, sdataRVA);
+                       moduleBuilder.ImplMap.Fixup(moduleBuilder);
+                       moduleBuilder.MethodSpec.Fixup(moduleBuilder);
+                       moduleBuilder.GenericParamConstraint.Fixup(moduleBuilder);
+
+                       // Import Address Table
+                       AssertRVA(mw, ImportAddressTableRVA);
+                       WriteRVA(mw, ImportHintNameTableRVA);
+                       WriteRVA(mw, 0);
+
+                       // CLI Header
+                       AssertRVA(mw, ComDescriptorRVA);
+                       cliHeader.MetaDataRVA = MetadataRVA;
+                       cliHeader.MetaDataSize = MetadataLength;
+                       if (ResourcesLength != 0)
+                       {
+                               cliHeader.ResourcesRVA = ResourcesRVA;
+                               cliHeader.ResourcesSize = ResourcesLength;
+                       }
+                       if (StrongNameSignatureLength != 0)
+                       {
+                               cliHeader.StrongNameSignatureRVA = StrongNameSignatureRVA;
+                               cliHeader.StrongNameSignatureSize = StrongNameSignatureLength;
+                       }
+                       cliHeader.Write(mw);
+
+                       // alignment padding
+                       for (int i = (int)(MethodBodiesRVA - (ComDescriptorRVA + ComDescriptorLength)); i > 0; i--)
+                       {
+                               mw.Write((byte)0);
+                       }
+
+                       // Method Bodies
+                       mw.Write(moduleBuilder.methodBodies);
+
+                       // alignment padding
+                       for (int i = (int)(ResourcesRVA - (MethodBodiesRVA + MethodBodiesLength)); i > 0; i--)
+                       {
+                               mw.Write((byte)0);
+                       }
+
+                       // Resources
+                       mw.Write(moduleBuilder.manifestResources);
+
+                       // The strong name signature live here (if it exists), but it will written later
+                       // and the following alignment padding will take care of reserving the space.
+
+                       // alignment padding
+                       for (int i = (int)(MetadataRVA - (ResourcesRVA + ResourcesLength)); i > 0; i--)
+                       {
+                               mw.Write((byte)0);
+                       }
+
+                       // Metadata
+                       AssertRVA(mw, MetadataRVA);
+                       moduleBuilder.WriteMetadata(mw);
+
+                       // Debug Directory
+                       AssertRVA(mw, DebugDirectoryRVA);
+                       WriteDebugDirectory(mw);
+
+                       // alignment padding
+                       for (int i = (int)(ImportDirectoryRVA - (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength)); i > 0; i--)
+                       {
+                               mw.Write((byte)0);
+                       }
+
+                       // Import Directory
+                       AssertRVA(mw, ImportDirectoryRVA);
+                       WriteImportDirectory(mw);
+
+                       // alignment padding
+                       for (int i = (int)(StartupStubRVA - (ImportDirectoryRVA + ImportDirectoryLength)); i > 0; i--)
+                       {
+                               mw.Write((byte)0);
+                       }
+
+                       // Startup Stub
+                       AssertRVA(mw, StartupStubRVA);
+                       if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64)
+                       {
+                               /*
+                                *   48 A1 00 20 40 00 00 00 00 00        mov         rax,qword ptr [0000000000402000h]
+                                *   FF E0                                jmp         rax
+                                */
+                               mw.Write((ushort)0xA148);
+                               mw.Write(peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
+                               mw.Write((ushort)0xE0FF);
+                       }
+                       else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
+                       {
+                               mw.Write(new byte[] {
+                                               0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
+                                               0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
+                                       });
+                               mw.Write(peWriter.Headers.OptionalHeader.ImageBase + StartupStubRVA);
+                               mw.Write(peWriter.Headers.OptionalHeader.ImageBase + BaseRVA);
+                       }
+                       else
+                       {
+                               mw.Write((ushort)0x25FF);
+                               mw.Write((uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
+                       }
+               }
+
+               [Conditional("DEBUG")]
+               private void AssertRVA(MetadataWriter mw, uint rva)
+               {
+                       Debug.Assert(mw.Position - PointerToRawData + BaseRVA == rva);
+               }
+
+               private void WriteDebugDirectory(MetadataWriter mw)
+               {
+                       if (DebugDirectoryLength != 0)
+                       {
+                               IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
+                               idd.Characteristics = 0;
+                               idd.TimeDateStamp = peWriter.Headers.FileHeader.TimeDateStamp;
+                               byte[] buf = SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd);
+                               idd.PointerToRawData = (DebugDirectoryRVA - BaseRVA) + DebugDirectoryLength + PointerToRawData;
+                               mw.Write(idd.Characteristics);
+                               mw.Write(idd.TimeDateStamp);
+                               mw.Write(idd.MajorVersion);
+                               mw.Write(idd.MinorVersion);
+                               mw.Write(idd.Type);
+                               mw.Write(idd.SizeOfData);
+                               mw.Write(idd.AddressOfRawData);
+                               mw.Write(idd.PointerToRawData);
+                               mw.Write(buf);
+                       }
+               }
+
+               private void WriteImportDirectory(MetadataWriter mw)
+               {
+                       mw.Write(ImportDirectoryRVA + 40);              // ImportLookupTable
+                       mw.Write(0);                                                    // DateTimeStamp
+                       mw.Write(0);                                                    // ForwarderChain
+                       mw.Write(ImportHintNameTableRVA + 14);  // Name
+                       mw.Write(ImportAddressTableRVA);
+                       mw.Write(new byte[20]);
+                       // Import Lookup Table
+                       mw.Write(ImportHintNameTableRVA);               // Hint/Name Table RVA
+                       int size = 48;
+                       if (peWriter.Headers.FileHeader.Machine != IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+                       {
+                               size += 4;
+                               mw.Write(0);
+                       }
+                       mw.Write(0);
+
+                       // alignment padding
+                       for (int i = (int)(ImportHintNameTableRVA - (ImportDirectoryRVA + size)); i > 0; i--)
+                       {
+                               mw.Write((byte)0);
+                       }
+
+                       // Hint/Name Table
+                       AssertRVA(mw, ImportHintNameTableRVA);
+                       mw.Write((ushort)0);            // Hint
+                       if ((peWriter.Headers.FileHeader.Characteristics & IMAGE_FILE_HEADER.IMAGE_FILE_DLL) != 0)
+                       {
+                               mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorDllMain"));
+                       }
+                       else
+                       {
+                               mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorExeMain"));
+                       }
+                       mw.Write((byte)0);
+                       // Name
+                       mw.Write(System.Text.Encoding.ASCII.GetBytes("mscoree.dll"));
+                       mw.Write((ushort)0);
+               }
+
+               internal int Length
+               {
+                       get { return (int)(StartupStubRVA - BaseRVA + StartupStubLength); }
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/Writer/VersionInfo.cs b/mcs/class/IKVM.Reflection/Writer/VersionInfo.cs
new file mode 100644 (file)
index 0000000..bfcc00b
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+  Copyright (C) 2008 Jeroen Frijters
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jeroen Frijters
+  jeroen@frijters.net
+  
+*/
+using System;
+using System.Globalization;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Writer
+{
+       sealed class VersionInfo
+       {
+               private AssemblyName name;
+               private string fileName;
+               internal string copyright;
+               internal string trademark;
+               internal string product;
+               internal string company;
+               private string description;
+               private string title;
+               internal string informationalVersion;
+               private string culture;
+               private string fileVersion;
+
+               internal void SetName(AssemblyName name)
+               {
+                       this.name = name;
+               }
+
+               internal void SetFileName(string assemblyFileName)
+               {
+                       this.fileName = assemblyFileName;
+               }
+
+               internal void SetAttribute(CustomAttributeBuilder cab)
+               {
+                       Universe u = cab.Constructor.Module.universe;
+                       Type type = cab.Constructor.DeclaringType;
+                       if (copyright == null && type == u.System_Reflection_AssemblyCopyrightAttribute)
+                       {
+                               copyright = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (trademark == null && type == u.System_Reflection_AssemblyTrademarkAttribute)
+                       {
+                               trademark = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (product == null && type == u.System_Reflection_AssemblyProductAttribute)
+                       {
+                               product = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (company == null && type == u.System_Reflection_AssemblyCompanyAttribute)
+                       {
+                               company = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (description == null && type == u.System_Reflection_AssemblyDescriptionAttribute)
+                       {
+                               description = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (title == null && type == u.System_Reflection_AssemblyTitleAttribute)
+                       {
+                               title = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (informationalVersion == null && type == u.System_Reflection_AssemblyInformationalVersionAttribute)
+                       {
+                               informationalVersion = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (culture == null && type == u.System_Reflection_AssemblyCultureAttribute)
+                       {
+                               culture  = (string)cab.GetConstructorArgument(0);
+                       }
+                       else if (fileVersion == null && type == u.System_Reflection_AssemblyFileVersionAttribute)
+                       {
+                               fileVersion = (string)cab.GetConstructorArgument(0);
+                       }
+               }
+
+               internal void Write(ByteBuffer bb)
+               {
+                       if (fileVersion == null)
+                       {
+                               if (name.Version != null)
+                               {
+                                       fileVersion = name.Version.ToString();
+                               }
+                               else
+                               {
+                                       fileVersion = "0.0.0.0";
+                               }
+                       }
+
+                       int codepage = 1200;    // Unicode codepage
+                       int lcid = 0x7f;
+                       if (name.CultureInfo != null)
+                       {
+                               lcid = name.CultureInfo.LCID;
+                       }
+                       if (culture != null)
+                       {
+                               lcid = new CultureInfo(culture).LCID;
+                       }
+
+                       Version filever = ParseVersionRobust(fileVersion);
+                       int fileVersionMajor = filever.Major;
+                       int fileVersionMinor = filever.Minor;
+                       int fileVersionBuild = filever.Build;
+                       int fileVersionRevision = filever.Revision;
+
+                       int productVersionMajor = fileVersionMajor;
+                       int productVersionMinor = fileVersionMinor;
+                       int productVersionBuild = fileVersionBuild;
+                       int productVersionRevision = fileVersionRevision;
+                       if (informationalVersion != null)
+                       {
+                               Version productver = ParseVersionRobust(informationalVersion);
+                               productVersionMajor = productver.Major;
+                               productVersionMinor = productver.Minor;
+                               productVersionBuild = productver.Build;
+                               productVersionRevision = productver.Revision;
+                       }
+
+                       ByteBuffer stringTable = new ByteBuffer(512);
+                       stringTable.Write((short)0);    // wLength (placeholder)
+                       stringTable.Write((short)0);    // wValueLength
+                       stringTable.Write((short)1);    // wType
+                       WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage));
+                       stringTable.Align(4);
+
+                       WriteString(stringTable, "Comments", description);
+                       WriteString(stringTable, "CompanyName", company);
+                       WriteString(stringTable, "FileDescription", title);
+                       WriteString(stringTable, "FileVersion", fileVersion);
+                       WriteString(stringTable, "InternalName", name.Name);
+                       WriteString(stringTable, "LegalCopyright", copyright);
+                       WriteString(stringTable, "LegalTrademarks", trademark);
+                       WriteString(stringTable, "OriginalFilename", fileName);
+                       WriteString(stringTable, "ProductName", product);
+                       WriteString(stringTable, "ProductVersion", informationalVersion);
+
+                       stringTable.Position = 0;
+                       stringTable.Write((short)stringTable.Length);
+
+                       ByteBuffer stringFileInfo = new ByteBuffer(512);
+                       stringFileInfo.Write((short)0); // wLength (placeholder)
+                       stringFileInfo.Write((short)0); // wValueLength
+                       stringFileInfo.Write((short)1); // wType
+                       WriteUTF16Z(stringFileInfo, "StringFileInfo");
+                       stringFileInfo.Align(4);
+                       stringFileInfo.Write(stringTable);
+                       stringFileInfo.Position = 0;
+                       stringFileInfo.Write((short)stringFileInfo.Length);
+
+                       byte[] preamble1 = new byte[] {
+                         // VS_VERSIONINFO (platform SDK)
+                         0x34, 0x00,                           // wValueLength
+                         0x00, 0x00,                           // wType
+                         0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00,  // "VS_VERSION_INFO\0"
+                         0x00, 0x00,                           // Padding1 (32 bit alignment)
+                         // VS_FIXEDFILEINFO starts
+                         0xBD, 0x04, 0xEF, 0xFE,       // dwSignature (0xFEEF04BD)
+                         0x00, 0x00, 0x01, 0x00,       // dwStrucVersion
+                       };
+                       byte[] preamble2 = new byte[] {
+                         0x3F, 0x00, 0x00, 0x00,       // dwFileFlagsMask (??)
+                         0x00, 0x00, 0x00, 0x00,       // dwFileFlags (??)
+                         0x04, 0x00, 0x00, 0x00,       // dwFileOS
+                         0x02, 0x00, 0x00, 0x00,       // dwFileType
+                         0x00, 0x00, 0x00, 0x00,       // dwFileSubtype
+                         0x00, 0x00, 0x00, 0x00,       // dwFileDateMS
+                         0x00, 0x00, 0x00, 0x00,       // dwFileDateLS
+                                                                               // Padding2 (32 bit alignment)
+                         // VarFileInfo
+                         0x44, 0x00,                           // wLength
+                         0x00, 0x00,                           // wValueLength
+                         0x01, 0x00,                           // wType
+                         0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00,       // "VarFileInfo\0"
+                         0x00, 0x00,                           // Padding
+                         // Var
+                         0x24, 0x00,                           // wLength
+                         0x04, 0x00,                           // wValueLength
+                         0x00, 0x00,                           // wType
+                         0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00,       // "Translation\0"
+                         0x00, 0x00,                           // Padding (32 bit alignment)
+                       };
+                       bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length));
+                       bb.Write(preamble1);
+                       bb.Write((short)fileVersionMinor);
+                       bb.Write((short)fileVersionMajor);
+                       bb.Write((short)fileVersionRevision);
+                       bb.Write((short)fileVersionBuild);
+                       bb.Write((short)productVersionMinor);
+                       bb.Write((short)productVersionMajor);
+                       bb.Write((short)productVersionRevision);
+                       bb.Write((short)productVersionBuild);
+                       bb.Write(preamble2);
+                       bb.Write((short)lcid);
+                       bb.Write((short)codepage);
+                       bb.Write(stringFileInfo);
+               }
+
+               private static void WriteUTF16Z(ByteBuffer bb, string str)
+               {
+                       foreach (char c in str)
+                       {
+                               bb.Write((short)c);
+                       }
+                       bb.Write((short)0);
+               }
+
+               private static void WriteString(ByteBuffer bb, string name, string value)
+               {
+                       value = value ?? " ";
+                       int pos = bb.Position;
+                       bb.Write((short)0);                                     // wLength (placeholder)
+                       bb.Write((short)(value.Length + 1));// wValueLength
+                       bb.Write((short)1);                                     // wType
+                       WriteUTF16Z(bb, name);
+                       bb.Align(4);
+                       WriteUTF16Z(bb, value);
+                       bb.Align(4);
+                       int savedPos = bb.Position;
+                       bb.Position = pos;
+                       bb.Write((short)(savedPos - pos));
+                       bb.Position = savedPos;
+               }
+
+               private static Version ParseVersionRobust(string ver)
+               {
+                       int index = 0;
+                       ushort major = ParseVersionPart(ver, ref index);
+                       ushort minor = ParseVersionPart(ver, ref index);
+                       ushort build = ParseVersionPart(ver, ref index);
+                       ushort revision = ParseVersionPart(ver, ref index);
+                       return new Version(major, minor, build, revision);
+               }
+
+               private static ushort ParseVersionPart(string str, ref int pos)
+               {
+                       ushort value = 0;
+                       while (pos < str.Length)
+                       {
+                               char c = str[pos];
+                               if (c == '.')
+                               {
+                                       pos++;
+                                       break;
+                               }
+                               else if (c >= '0' && c <= '9')
+                               {
+                                       value *= 10;
+                                       value += (ushort)(c - '0');
+                                       pos++;
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+                       return value;
+               }
+       }
+}
diff --git a/mcs/class/IKVM.Reflection/reflect.build b/mcs/class/IKVM.Reflection/reflect.build
new file mode 100644 (file)
index 0000000..972aacc
--- /dev/null
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<project name="reflect" default="IKVM.Reflection">
+    <target name="IKVM.Reflection">
+        <property name="defs" value="TRACE" />
+        <if test="${framework::exists('mono-2.0')}">
+            <property name="defs" value="${defs};MONO" />
+        </if>
+        <if test="${property::exists('signed')}">
+            <property name="defs" value="${defs};${signed}" />
+        </if>
+        <if test="${version::get-major(framework::get-version(framework::get-target-framework() )) == 4}">
+            <property name="defs" value="${defs};NET_4_0" />
+        </if>
+        <!-- workaround for the fact that <include if="${framework::exists('mono-2.0')} ...> still insists on evaluating the name attribute -->
+        <property name="MonoSymbolWriter" value="dummy.dll" />
+        <if test="${framework::exists('mono-2.0')}">
+            <property name="MonoSymbolWriter" value="${path::combine(framework::get-assembly-directory('mono-2.0'), 'Mono.CompilerServices.SymbolWriter.dll')}" />
+        </if>
+        <csc target="library" output="../bin/IKVM.Reflection.dll" optimize="true" define="${defs}">
+            <sources>
+                <include name="../CommonAssemblyInfo.cs" />
+                <include name="AmbiguousMatchException.cs" />
+                <include name="Assembly.cs" />
+                <include name="AssemblyName.cs" />
+                <include name="BadImageFormatException.cs" />
+                <include name="Binder.cs" />
+                <include name="ConstructorInfo.cs" />
+                <include name="CustomAttributeData.cs" />
+                <include name="CustomAttributeNamedArgument.cs" />
+                <include name="CustomAttributeTypedArgument.cs" />
+                <include name="Enums.cs" />
+                <include name="EventInfo.cs" />
+                <include name="ExceptionHandlingClause.cs" />
+                <include name="FieldInfo.cs" />
+                <include name="FieldSignature.cs" />
+                <include name="Fusion.cs" />
+                <include name="GenericWrappers.cs" />
+                <include name="InterfaceMapping.cs" />
+                <include name="LocalVariableInfo.cs" />
+                <include name="ManifestResourceInfo.cs" />
+                <include name="MarshalSpec.cs" />
+                <include name="MemberInfo.cs" />
+                <include name="MethodBase.cs" />
+                <include name="MethodBody.cs" />
+                <include name="MethodImplMap.cs" />
+                <include name="MethodInfo.cs" />
+                <include name="MethodSignature.cs" />
+                <include name="Module.cs" />
+                <include name="ParameterInfo.cs" />
+                <include name="ParameterModifier.cs" />
+                <include name="PropertyInfo.cs" />
+                <include name="PropertySignature.cs" />
+                <include name="Signature.cs" />
+                <include name="StandAloneMethodSig.cs" />
+                <include name="StrongNameKeyPair.cs" />
+                <include name="Type.cs" />
+                <include name="TypeNameParser.cs" />
+                <include name="Universe.cs" />
+                <include name="Util.cs" />
+                <include name="Emit\AssemblyBuilder.cs" />
+                <include name="Emit\ConstructorBuilder.cs" />
+                <include name="Emit\CustomAttributeBuilder.cs" />
+                <include name="Emit\EnumBuilder.cs" />
+                <include name="Emit\Enums.cs" />
+                <include name="Emit\EventBuilder.cs" />
+                <include name="Emit\FieldBuilder.cs" />
+                <include name="Emit\ILGenerator.cs" />
+                <include name="Emit\MethodBuilder.cs" />
+                <include name="Emit\ModuleBuilder.cs" />
+                <include name="Emit\OpCode.cs" />
+                <include name="Emit\OpCodes.cs" />
+                <include name="Emit\ParameterBuilder.cs" />
+                <include name="Emit\PropertyBuilder.cs" />
+                <include name="Emit\SignatureHelper.cs" />
+                <include name="Emit\Tokens.cs" />
+                <include name="Emit\TypeBuilder.cs" />
+                <include name="Impl\CryptoConvert.cs" />
+                <include name="Impl\CryptoHack.cs" />
+                <include name="Impl\ITypeOwner.cs" />
+                <include name="Impl\MdbWriter.cs" />
+                <include name="Impl\PdbWriter.cs" />
+                <include name="Impl\SymbolSupport.cs" />
+                <include name="Metadata\CliHeader.cs" />
+                <include name="Metadata\MetadataRW.cs" />
+                <include name="Metadata\Tables.cs" />
+                <include name="Properties\AssemblyInfo.cs" />
+                <include name="Reader\AssemblyReader.cs" />
+                <include name="Reader\ByteReader.cs" />
+                <include name="Reader\EventInfoImpl.cs" />
+                <include name="Reader\Field.cs" />
+                <include name="Reader\GenericTypeParameter.cs" />
+                <include name="Reader\MetadataReader.cs" />
+                <include name="Reader\Method.cs" />
+                <include name="Reader\ModuleReader.cs" />
+                <include name="Reader\PEReader.cs" />
+                <include name="Reader\PropertyInfoImpl.cs" />
+                <include name="Reader\ResourceModule.cs" />
+                <include name="Reader\TypeDefImpl.cs" />
+                <include name="Writer\ByteBuffer.cs" />
+                <include name="Writer\Heaps.cs" />
+                <include name="Writer\MetadataWriter.cs" />
+                <include name="Writer\ModuleWriter.cs" />
+                <include name="Writer\PEWriter.cs" />
+                <include name="Writer\ResourceSection.cs" />
+                <include name="Writer\TextSection.cs" />
+                <include name="Writer\VersionInfo.cs" />
+            </sources>
+            <references>
+                <include if="${framework::exists('mono-2.0')}" name="${MonoSymbolWriter}" />
+            </references>
+        </csc>
+    </target>
+</project>