Writer.cs :  » Development » Sandcastle » Microsoft » Cci » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » Sandcastle 
Sandcastle » Microsoft » Cci » Writer.cs
// Copyright  Microsoft Corporation.
// This source file is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.

#if !NoWriter
using System;
using System.Collections;
#if CCINamespace
using Microsoft.Cci.Metadata;
#else
using System.Compiler.Metadata;
#endif
using System.Diagnostics;
using System.IO;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security;
#if !ROTOR
using System.Security.Cryptography;
#endif
using System.Text;

#if CCINamespace
namespace Microsoft.Cci{
#else
namespace System.Compiler
{
#endif
#if !ROTOR
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006"), SuppressUnmanagedCodeSecurity]
    interface ISymUnmanagedDocumentWriter
    {
        void SetSource(uint sourceSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] source);
        void SetCheckSum(ref Guid algorithmId, uint checkSumSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] checkSum);
    };
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("2DE91396-3844-3B1D-8E91-41C24FD672EA"), SuppressUnmanagedCodeSecurity]
    interface ISymUnmanagedWriter
    {
        ISymUnmanagedDocumentWriter DefineDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType);
        void SetUserEntryPoint(uint entryMethod);
        void OpenMethod(uint method);
        void CloseMethod();
        uint OpenScope(uint startOffset);
        void CloseScope(uint endOffset);
        void SetScopeRange(uint scopeID, uint startOffset, uint endOffset);
        void DefineLocalVariable(string name, uint attributes, uint cSig, IntPtr signature, uint addrKind, uint addr1, uint addr2, uint startOffset, uint endOffset);
        void DefineParameter(string name, uint attributes, uint sequence, uint addrKind, uint addr1, uint addr2, uint addr3);
        void DefineField(uint parent, string name, uint attributes, uint cSig, IntPtr signature, uint addrKind, uint addr1, uint addr2, uint addr3);
        void DefineGlobalVariable(string name, uint attributes, uint cSig, IntPtr signature, uint addrKind, uint addr1, uint addr2, uint addr3);
        void Close();
        void SetSymAttribute(uint parent, string name, uint cData, IntPtr signature);
        void OpenNamespace(string name);
        void CloseNamespace();
        void UsingNamespace(string fullName);
        void SetMethodSourceRange(ISymUnmanagedDocumentWriter startDoc, uint startLine, uint startColumn, object endDoc, uint endLine, uint endColumn);
        void Initialize([MarshalAs(UnmanagedType.IUnknown)]object emitter, string filename, [MarshalAs(UnmanagedType.IUnknown)]object pIStream, bool fFullBuild);
        void GetDebugInfo(ref ImageDebugDirectory pIDD, uint cData, out uint pcData, IntPtr data);
        void DefineSequencePoints(ISymUnmanagedDocumentWriter document, uint spCount,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] offsets,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] lines,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] columns,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] endLines,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] endColumns);
        void RemapToken(uint oldToken, uint newToken);
        void Initialize2([MarshalAs(UnmanagedType.IUnknown)]object emitter, string tempfilename, [MarshalAs(UnmanagedType.IUnknown)]object pIStream, bool fFullBuild, string finalfilename);
        void DefineConstant(string name, object value, uint cSig, IntPtr signature);
    }
    struct ImageDebugDirectory
    {
        internal int Characteristics;
        internal int TimeDateStamp;
        internal short MajorVersion;
        internal short MinorVersion;
        internal int Type;
        internal int SizeOfData;
        internal int AddressOfRawData;
        internal int PointerToRawData;
        public ImageDebugDirectory(bool zeroFill)
        {
            this.Characteristics = 0;
            this.TimeDateStamp = 0;
            this.MajorVersion = 0;
            this.MinorVersion = 0;
            this.Type = 0;
            this.SizeOfData = 0;
            this.AddressOfRawData = 0;
            this.PointerToRawData = 0;
        }
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("BA3FEE4C-ECB9-4e41-83B7-183FA41CD859")]
    unsafe public interface IMetaDataEmit
    {
        void SetModuleProps(string szName);
        void Save(string szFile, uint dwSaveFlags);
        void SaveToStream(void* pIStream, uint dwSaveFlags);
        uint GetSaveSize(uint fSave);
        uint DefineTypeDef(char* szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint* rtkImplements);
        uint DefineNestedType(char* szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint* rtkImplements, uint tdEncloser);
        void SetHandler([MarshalAs(UnmanagedType.IUnknown), In]object pUnk);
        uint DefineMethod(uint td, char* zName, uint dwMethodFlags, byte* pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags);
        void DefineMethodImpl(uint td, uint tkBody, uint tkDecl);
        uint DefineTypeRefByName(uint tkResolutionScope, char* szName);
        uint DefineImportType(IntPtr pAssemImport, void* pbHashValue, uint cbHashValue, IMetaDataImport pImport,
          uint tdImport, IntPtr pAssemEmit);
        uint DefineMemberRef(uint tkImport, string szName, byte* pvSigBlob, uint cbSigBlob);
        uint DefineImportMember(IntPtr pAssemImport, void* pbHashValue, uint cbHashValue,
          IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent);
        uint DefineEvent(uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint* rmdOtherMethods);
        void SetClassLayout(uint td, uint dwPackSize, COR_FIELD_OFFSET* rFieldOffsets, uint ulClassSize);
        void DeleteClassLayout(uint td);
        void SetFieldMarshal(uint tk, byte* pvNativeType, uint cbNativeType);
        void DeleteFieldMarshal(uint tk);
        uint DefinePermissionSet(uint tk, uint dwAction, void* pvPermission, uint cbPermission);
        void SetRVA(uint md, uint ulRVA);
        uint GetTokenFromSig(byte* pvSig, uint cbSig);
        uint DefineModuleRef(string szName);
        void SetParent(uint mr, uint tk);
        uint GetTokenFromTypeSpec(byte* pvSig, uint cbSig);
        void SaveToMemory(void* pbData, uint cbData);
        uint DefineUserString(string szString, uint cchString);
        void DeleteToken(uint tkObj);
        void SetMethodProps(uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags);
        void SetTypeDefProps(uint td, uint dwTypeDefFlags, uint tkExtends, uint* rtkImplements);
        void SetEventProps(uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint* rmdOtherMethods);
        uint SetPermissionSetProps(uint tk, uint dwAction, void* pvPermission, uint cbPermission);
        void DefinePinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL);
        void SetPinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL);
        void DeletePinvokeMap(uint tk);
        uint DefineCustomAttribute(uint tkObj, uint tkType, void* pCustomAttribute, uint cbCustomAttribute);
        void SetCustomAttributeValue(uint pcv, void* pCustomAttribute, uint cbCustomAttribute);
        uint DefineField(uint td, string szName, uint dwFieldFlags, byte* pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, void* pValue, uint cchValue);
        uint DefineProperty(uint td, string szProperty, uint dwPropFlags, byte* pvSig, uint cbSig, uint dwCPlusTypeFlag,
          void* pValue, uint cchValue, uint mdSetter, uint mdGetter, uint* rmdOtherMethods);
        uint DefineParam(uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue);
        void SetFieldProps(uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue);
        void SetPropertyProps(uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue, uint mdSetter, uint mdGetter, uint* rmdOtherMethods);
        void SetParamProps(uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue);
        uint DefineSecurityAttributeSet(uint tkObj, IntPtr rSecAttrs, uint cSecAttrs);
        void ApplyEditAndContinue([MarshalAs(UnmanagedType.IUnknown)]object pImport);
        uint TranslateSigWithScope(IntPtr pAssemImport, void* pbHashValue, uint cbHashValue,
          IMetaDataImport import, byte* pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, byte* pvTranslatedSig, uint cbTranslatedSigMax);
        void SetMethodImplFlags(uint md, uint dwImplFlags);
        void SetFieldRVA(uint fd, uint ulRVA);
        void Merge(IMetaDataImport pImport, IntPtr pHostMapToken, [MarshalAs(UnmanagedType.IUnknown)]object pHandler);
        void MergeEnd();
    }
    public struct COR_FIELD_OFFSET
    {
        public uint ridOfField;
        public uint ulOffset;
    }
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44")]
    unsafe public interface IMetaDataImport
    {
        [PreserveSig]
        void CloseEnum(uint hEnum);
        uint CountEnum(uint hEnum);
        void ResetEnum(uint hEnum, uint ulPos);
        uint EnumTypeDefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeDefs, uint cMax);
        uint EnumInterfaceImpls(ref uint phEnum, uint td, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rImpls, uint cMax);
        uint EnumTypeRefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeRefs, uint cMax);
        uint FindTypeDefByName(string szTypeDef, uint tkEnclosingClass);
        Guid GetScopeProps(StringBuilder szName, uint cchName, out uint pchName);
        uint GetModuleFromScope();
        uint GetTypeDefProps(uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags);
        uint GetInterfaceImplProps(uint iiImpl, out uint pClass);
        uint GetTypeRefProps(uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName);
        uint ResolveTypeRef(uint tr, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppIScope);
        uint EnumMembers(ref uint phEnum, uint cl, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rMembers, uint cMax);
        uint EnumMembersWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMembers, uint cMax);
        uint EnumMethods(ref uint phEnum, uint cl, uint* rMethods, uint cMax);
        uint EnumMethodsWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethods, uint cMax);
        uint EnumFields(ref uint phEnum, uint cl, uint* rFields, uint cMax);
        uint EnumFieldsWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rFields, uint cMax);
        uint EnumParams(ref uint phEnum, uint mb, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rParams, uint cMax);
        uint EnumMemberRefs(ref uint phEnum, uint tkParent, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rMemberRefs, uint cMax);
        uint EnumMethodImpls(ref uint phEnum, uint td, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethodBody,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethodDecl, uint cMax);
        uint EnumPermissionSets(ref uint phEnum, uint tk, uint dwActions, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rPermission,
          uint cMax);
        uint FindMember(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob);
        uint FindMethod(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob);
        uint FindField(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob);
        uint FindMemberRef(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob);
        uint GetMethodProps(uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr,
          IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA);
        unsafe uint GetMemberRefProps(uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out byte* ppvSigBlob);
        uint EnumProperties(ref uint phEnum, uint td, uint* rProperties, uint cMax);
        uint EnumEvents(ref uint phEnum, uint td, uint* rEvents, uint cMax);
        uint GetEventProps(uint ev, out uint pClass, StringBuilder szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags,
          out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 11)] uint[] rmdOtherMethod, uint cMax);
        uint EnumMethodSemantics(ref uint phEnum, uint mb, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rEventProp, uint cMax);
        uint GetMethodSemantics(uint mb, uint tkEventProp);
        uint GetClassLayout(uint td, out uint pdwPackSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] COR_FIELD_OFFSET[] rFieldOffset, uint cMax, out uint pcFieldOffset);
        unsafe uint GetFieldMarshal(uint tk, out byte* ppvNativeType);
        uint GetRVA(uint tk, out uint pulCodeRVA);
        unsafe uint GetPermissionSetProps(uint pm, out uint pdwAction, out void* ppvPermission);
        unsafe uint GetSigFromToken(uint mdSig, out byte* ppvSig);
        uint GetModuleRefProps(uint mur, StringBuilder szName, uint cchName);
        uint EnumModuleRefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rModuleRefs, uint cmax);
        unsafe uint GetTypeSpecFromToken(uint typespec, out byte* ppvSig);
        uint GetNameFromToken(uint tk);
        uint EnumUnresolvedMethods(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rMethods, uint cMax);
        uint GetUserString(uint stk, StringBuilder szString, uint cchString);
        uint GetPinvokeMap(uint tk, out uint pdwMappingFlags, StringBuilder szImportName, uint cchImportName, out uint pchImportName);
        uint EnumSignatures(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rSignatures, uint cmax);
        uint EnumTypeSpecs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeSpecs, uint cmax);
        uint EnumUserStrings(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rStrings, uint cmax);
        [PreserveSig]
        int GetParamForMethodIndex(uint md, uint ulParamSeq, out uint pParam);
        uint EnumCustomAttributes(ref uint phEnum, uint tk, uint tkType, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rCustomAttributes, uint cMax);
        uint GetCustomAttributeProps(uint cv, out uint ptkObj, out uint ptkType, out void* ppBlob);
        uint FindTypeRef(uint tkResolutionScope, string szName);
        uint GetMemberProps(uint mb, out uint pClass, StringBuilder szMember, uint cchMember, out uint pchMember, out uint pdwAttr,
          out byte* ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out void* ppValue);
        uint GetFieldProps(uint mb, out uint pClass, StringBuilder szField, uint cchField, out uint pchField, out uint pdwAttr,
          out byte* ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out void* ppValue);
        uint GetPropertyProps(uint prop, out uint pClass, StringBuilder szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags,
          out byte* ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out void* ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter,
          out uint pmdGetter, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 14)] uint[] rmdOtherMethod, uint cMax);
        uint GetParamProps(uint tk, out uint pmd, out uint pulSequence, StringBuilder szName, uint cchName, out uint pchName,
          out uint pdwAttr, out uint pdwCPlusTypeFlag, out void* ppValue);
        uint GetCustomAttributeByName(uint tkObj, string szName, out void* ppData);
        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Bool)]
        bool IsValidToken(uint tk);
        uint GetNestedClassProps(uint tdNestedClass);
        uint GetNativeCallConvFromSig(void* pvSig, uint cbSig);
        int IsGlobal(uint pd);
    }
    [SuppressUnmanagedCodeSecurity]
    internal sealed class Ir2md : IMetaDataEmit, IMetaDataImport
    {
#else
  internal sealed class Ir2md{
#endif
        private AssemblyNode assembly;
        private Module/*!*/ module;
        private MetadataWriter/*!*/ writer;
        private bool UseGenerics = false;
        private bool StripOptionalModifiersFromLocals
        {
            get { return this.module.StripOptionalModifiersFromLocals; }
        }
        private BinaryWriter/*!*/ blobHeap = new BinaryWriter(new MemoryStream(), System.Text.Encoding.Unicode);
#if WHIDBEYwithGenerics || WHIDBEYwithGenericsAndIEqualityComparer
        private Hashtable/*!*/ blobHeapIndex = new Hashtable(new ByteArrayKeyComparer());
#else
    private Hashtable/*!*/ blobHeapIndex = new Hashtable(new ByteArrayHasher(), new ByteArrayComparer());
#endif
        private Hashtable/*!*/ blobHeapStringIndex = new Hashtable();
        private NodeList/*!*/ nodesWithCustomAttributes = new NodeList();
        private int customAttributeCount = 0;
        private NodeList/*!*/ nodesWithSecurityAttributes = new NodeList();
        private int securityAttributeCount = 0;
        private NodeList/*!*/ constantTableEntries = new NodeList();
        private TrivialHashtable/*!*/ assemblyRefIndex = new TrivialHashtable();
        private AssemblyReferenceList/*!*/ assemblyRefEntries = new AssemblyReferenceList();
        private TypeNodeList/*!*/ classLayoutEntries = new TypeNodeList();
        private TrivialHashtable/*!*/ documentMap = new TrivialHashtable();
        private TrivialHashtable/*!*/ eventIndex = new TrivialHashtable();
        private EventList/*!*/ eventEntries = new EventList();
        private TrivialHashtable/*!*/ eventMapIndex = new TrivialHashtable();
        private EventList/*!*/ eventMapEntries = new EventList();
        private TrivialHashtable/*!*/ exceptionBlock = new TrivialHashtable();
        private TrivialHashtable/*!*/ fieldIndex = new TrivialHashtable();
        private FieldList/*!*/ fieldEntries = new FieldList();
        private FieldList/*!*/ fieldLayoutEntries = new FieldList();
        private FieldList/*!*/ fieldRvaEntries = new FieldList();
        private Hashtable/*!*/ fileTableIndex = new Hashtable();
        private ModuleList/*!*/ fileTableEntries = new ModuleList();
        private Hashtable/*!*/ genericParamIndex = new Hashtable();
        private MemberList/*!*/ genericParamEntries = new MemberList();
        private TypeNodeList/*!*/ genericParameters = new TypeNodeList();
        private TypeNodeList/*!*/ genericParamConstraintEntries = new TypeNodeList();
        private ArrayList/*!*/ guidEntries = new ArrayList();
        private Hashtable/*!*/ guidIndex = new Hashtable();
        private MethodList/*!*/ implMapEntries = new MethodList();
        private TypeNodeList/*!*/ interfaceEntries = new TypeNodeList();
        private NodeList/*!*/ marshalEntries = new NodeList();
        private TrivialHashtable/*!*/ memberRefIndex = new TrivialHashtable();
        private MemberList/*!*/ memberRefEntries = new MemberList();
        private TrivialHashtable/*!*/ methodBodiesHeapIndex = new TrivialHashtable();
        private BinaryWriter/*!*/ methodBodiesHeap = new BinaryWriter(new MemoryStream());
        private BinaryWriter/*!*/ methodBodyHeap;
        private MethodList/*!*/ methodEntries = new MethodList();
        private TrivialHashtable/*!*/ methodIndex = new TrivialHashtable();
        private MethodList/*!*/ methodImplEntries = new MethodList();
        private MethodInfo/*!*/ methodInfo;
        private Method currentMethod;
        private MemberList/*!*/ methodSemanticsEntries = new MemberList();
        private MethodList/*!*/ methodSpecEntries = new MethodList();
        private Hashtable/*!*/ methodSpecIndex = new Hashtable();
        private ModuleReferenceList/*!*/ moduleRefEntries = new ModuleReferenceList();
        private Hashtable/*!*/ moduleRefIndex = new Hashtable();
        private TypeNodeList/*!*/ nestedClassEntries = new TypeNodeList();
        private TrivialHashtable/*!*/ paramIndex = new TrivialHashtable();
        private ParameterList/*!*/ paramEntries = new ParameterList();
        private TrivialHashtable/*!*/ propertyIndex = new TrivialHashtable();
        private PropertyList/*!*/ propertyEntries = new PropertyList();
        private TrivialHashtable/*!*/ propertyMapIndex = new TrivialHashtable();
        private PropertyList/*!*/ propertyMapEntries = new PropertyList();
        private BinaryWriter/*!*/ resourceDataHeap = new BinaryWriter(new MemoryStream());
        private BinaryWriter/*!*/ sdataHeap = new BinaryWriter(new MemoryStream());
#if !ROTOR
        private ISymUnmanagedWriter symWriter = null;
#endif
        private int stackHeight;
        private int stackHeightMax;
        private int stackHeightExitTotal;
        private ArrayList/*!*/ standAloneSignatureEntries = new ArrayList();
        private BinaryWriter/*!*/ stringHeap = new BinaryWriter(new MemoryStream());
        private Hashtable/*!*/ stringHeapIndex = new Hashtable();
        private BinaryWriter/*!*/ tlsHeap = new BinaryWriter(new MemoryStream());
        private TrivialHashtable/*!*/ typeDefIndex = new TrivialHashtable();
        private TypeNodeList/*!*/ typeDefEntries = new TypeNodeList();
        private TrivialHashtable/*!*/ typeRefIndex = new TrivialHashtable();
        private TypeNodeList/*!*/ typeRefEntries = new TypeNodeList();
        private TrivialHashtable/*!*/ typeSpecIndex = new TrivialHashtable();
        private TypeNodeList/*!*/ typeSpecEntries = new TypeNodeList();
        private TrivialHashtable/*!*/ typeParameterNumber = new TrivialHashtable();
        private BinaryWriter/*!*/ userStringHeap = new BinaryWriter(new MemoryStream(), System.Text.Encoding.Unicode);
        private Hashtable/*!*/ userStringHeapIndex = new Hashtable();
        private byte[] PublicKey;

        internal Ir2md(Module/*!*/ module)
        {
            this.assembly = module as AssemblyNode;
            this.module = module;
            //^ base();
            this.blobHeap.Write((byte)0);
            this.stringHeap.Write((byte)0);
            this.userStringHeap.Write((byte)0);
            if (this.assembly != null)
                this.PublicKey = this.assembly.PublicKeyOrToken;
        }
        internal static void WritePE(Module/*!*/ module, string debugSymbolsLocation, BinaryWriter/*!*/ writer)
        {
            Ir2md ir2md = new Ir2md(module);
            try
            {
                ir2md.SetupMetadataWriter(debugSymbolsLocation);
                MetadataWriter mdWriter = ir2md.writer;
                mdWriter.WritePE(writer);
            }
            finally
            {
#if !ROTOR
                if (ir2md.symWriter != null)
                    ir2md.symWriter.Close();
#endif
                ir2md.assembly = null;
                ir2md.assemblyRefEntries = null;
                ir2md.assemblyRefIndex = null;
                ir2md.blobHeap = null;
                ir2md.blobHeapIndex = null;
                ir2md.blobHeapStringIndex = null;
                ir2md.classLayoutEntries = null;
                ir2md.constantTableEntries = null;
                ir2md.documentMap = null;
                ir2md.eventEntries = null;
                ir2md.eventIndex = null;
                ir2md.eventMapEntries = null;
                ir2md.eventMapIndex = null;
                ir2md.exceptionBlock = null;
                ir2md.fieldEntries = null;
                ir2md.fieldIndex = null;
                ir2md.fieldLayoutEntries = null;
                ir2md.fieldRvaEntries = null;
                ir2md.fileTableEntries = null;
                ir2md.fileTableIndex = null;
                ir2md.genericParamConstraintEntries = null;
                ir2md.genericParamEntries = null;
                ir2md.genericParameters = null;
                ir2md.genericParamIndex = null;
                ir2md.guidEntries = null;
                ir2md.guidIndex = null;
                ir2md.implMapEntries = null;
                ir2md.interfaceEntries = null;
                ir2md.marshalEntries = null;
                ir2md.memberRefEntries = null;
                ir2md.memberRefIndex = null;
                ir2md.methodBodiesHeap = null;
                ir2md.methodBodiesHeapIndex = null;
                ir2md.methodBodyHeap = null;
                ir2md.methodEntries = null;
                ir2md.methodImplEntries = null;
                ir2md.methodIndex = null;
                ir2md.methodInfo = null;
                ir2md.currentMethod = null;
                ir2md.methodSemanticsEntries = null;
                ir2md.methodSpecEntries = null;
                ir2md.methodSpecIndex = null;
                ir2md.module = null;
                ir2md.moduleRefEntries = null;
                ir2md.moduleRefIndex = null;
                ir2md.nestedClassEntries = null;
                ir2md.nodesWithCustomAttributes = null;
                ir2md.nodesWithSecurityAttributes = null;
                ir2md.paramEntries = null;
                ir2md.paramIndex = null;
                ir2md.propertyEntries = null;
                ir2md.propertyIndex = null;
                ir2md.propertyMapEntries = null;
                ir2md.propertyMapIndex = null;
                ir2md.PublicKey = null;
                ir2md.resourceDataHeap = null;
                ir2md.sdataHeap = null;
                ir2md.standAloneSignatureEntries = null;
                ir2md.stringHeap = null;
                ir2md.stringHeapIndex = null;
#if !ROTOR
                ir2md.symWriter = null;
#endif
                ir2md.tlsHeap = null;
                ir2md.typeDefEntries = null;
                ir2md.typeDefIndex = null;
                ir2md.typeParameterNumber = null;
                ir2md.typeRefEntries = null;
                ir2md.typeRefIndex = null;
                ir2md.typeSpecEntries = null;
                ir2md.typeSpecIndex = null;
                ir2md.unspecializedFieldFor = null;
                ir2md.unspecializedMethodFor = null;
                ir2md.userStringHeap = null;
                ir2md.userStringHeapIndex = null;
                ir2md.writer = null;
                ir2md = null;
            }
        }

        private static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
        private static Guid IID_IClassFactory = new Guid("00000001-0000-0000-C000-000000000046");

        [ComImport(), Guid("00000001-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        interface IClassFactory
        {
            int CreateInstance(
                   [In, MarshalAs(UnmanagedType.Interface)] object unused,
                   [In] ref Guid refiid,
                   [MarshalAs(UnmanagedType.Interface)] out Object ppunk);
            int LockServer(
                   int fLock);
        }

        delegate int GetClassObjectDelegate([In] ref Guid refclsid,
                                            [In] ref Guid refiid,
                                            [MarshalAs(UnmanagedType.Interface)] out IClassFactory ppUnk);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        private static extern int LoadLibrary(string lpFileName);
        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        private static extern GetClassObjectDelegate GetProcAddress(int hModule, string lpProcName);

        private object CrossCompileActivate(string server, Guid guid)
        {
            // Poor man's version of Activator.CreateInstance or CoCreate
            object o = null;
            int hmod = LoadLibrary(server);
            if (hmod != 0)
            {
                GetClassObjectDelegate del = GetProcAddress(hmod, "DllGetClassObject");
                if (del != null)
                {
                    IClassFactory icf;
                    int hr = del(ref guid, ref IID_IClassFactory, out icf);
                    if (hr == 0 && icf != null)
                    {
                        object temp = null;
                        hr = icf.CreateInstance(null, ref IID_IUnknown, out temp);
                        if (hr == 0) o = temp;
                    }
                }
            }
            return o;
        }
        private void SetupMetadataWriter(string debugSymbolsLocation)
        {
            Version v = TargetPlatform.TargetVersion;
            this.UseGenerics = TargetPlatform.UseGenerics;
#if !ROTOR
            if (debugSymbolsLocation != null)
            {
                // If targeting RTM (Version.Major = 1 and Version.Minor = 0)
                // then use Symwriter.pdb as ProgID else use CorSymWriter_SxS
                // (Note that RTM version 1.0.3705 has Assembly version 1.0.3300,
                // hence the <= 3705 expression.  This also leaves room for RTM SP releases
                // with slightly different build numbers).
                Type t = null;
                if (v.Major == 1 && v.Minor == 0 && v.Build <= 3705)
                {
                    try
                    {
                        t = Type.GetTypeFromProgID("Symwriter.pdb", false);
                        this.symWriter = (ISymUnmanagedWriter)Activator.CreateInstance(t);
                        if (this.symWriter != null)
                            this.symWriter.Initialize(this, debugSymbolsLocation, null, true);
                    }
                    catch (Exception)
                    {
                        t = null;
                        this.symWriter = null;
                    }
                }
                if (t == null)
                {
                    Debug.Assert(this.symWriter == null);
                    t = Type.GetTypeFromProgID("CorSymWriter_SxS", false);
                    if (t != null)
                    {
                        Guid guid = t.GUID;

                        // If the compiler was built with Whidbey, then mscoree will pick a matching
                        // diasymreader.dll out of the Whidbey directory.  But if we are cross-
                        // compiling, this is *NOT* what we want.  Instead, we want to override
                        // the shim's logic and explicitly pick a diasymreader.dll from the place
                        // that matches the version of the output file we are emitting.  This is
                        // strictly illegal by the CLR's rules.  However, the CLR does not yet
                        // support cross-compilation, so we have little choice.
                        if (!UseGenerics)
                        {
                            Version vcompiler = typeof(object).Assembly.GetName().Version;
                            if (vcompiler.Major >= 2)
                            {
                                // This is the only cross-compilation case we currently support.
                                string server = Path.Combine(Path.GetDirectoryName(typeof(object).Assembly.Location),
                                                                                 "..\\v1.1.4322\\diasymreader.dll");
                                object o = CrossCompileActivate(server, guid);
                                this.symWriter = (ISymUnmanagedWriter)o;
                            }
                        }
                        if (this.symWriter == null)
                        {
                            this.symWriter = (ISymUnmanagedWriter)Activator.CreateInstance(t);
                        }
                        if (this.symWriter != null)
                            this.symWriter.Initialize(this, debugSymbolsLocation, null, true);
                    }
                    else
                    {
                        throw new DebugSymbolsCouldNotBeWrittenException();
                    }
                }
            }
#endif
            //Visit the module, building lists etc.
            this.VisitModule(this.module);
            //Use the lists to populate the tables in the metadata writer
#if !ROTOR
            MetadataWriter writer = this.writer = new MetadataWriter(this.symWriter);
#else
      MetadataWriter writer = this.writer = new MetadataWriter();
#endif
            writer.UseGenerics = this.UseGenerics;
            if (module.EntryPoint != null)
            {
                writer.entryPointToken = this.GetMethodToken(module.EntryPoint);
#if !ROTOR
                if (this.symWriter != null) this.symWriter.SetUserEntryPoint((uint)writer.entryPointToken);
#endif
            }
            writer.moduleKind = module.Kind;
            writer.peKind = module.PEKind;
            writer.TrackDebugData = module.TrackDebugData;
            writer.fileAlignment = module.FileAlignment;
            if (writer.fileAlignment < 512) writer.fileAlignment = 512;
            writer.PublicKey = this.PublicKey;
            if (this.assembly != null) this.PopulateAssemblyTable();
            this.PopulateClassLayoutTable();
            this.PopulateConstantTable();
            this.PopulateGenericParamTable(); //Needs to happen before PopulateCustomAttributeTable since it the latter refers to indices in the sorted table
            this.PopulateCustomAttributeTable();
            this.PopulateDeclSecurityTable();
            this.PopulateEventMapTable();
            this.PopulateEventTable();
            this.PopulateExportedTypeTable();
            this.PopulateFieldTable();
            this.PopulateFieldLayoutTable();
            this.PopulateFieldRVATable();
            this.PopulateManifestResourceTable(); //This needs to happen before PopulateFileTable because resources are not visited separately
            this.PopulateFileTable();
            this.PopulateGenericParamConstraintTable();
            this.PopulateImplMapTable();
            this.PopulateInterfaceImplTable();
            this.PopulateMarshalTable();
            this.PopulateMethodTable();
            this.PopulateMethodImplTable();
            this.PopulateMemberRefTable();
            this.PopulateMethodSemanticsTable();
            this.PopulateMethodSpecTable();
            this.PopulateModuleTable();
            this.PopulateModuleRefTable();
            this.PopulateNestedClassTable();
            this.PopulateParamTable();
            this.PopulatePropertyTable();
            this.PopulatePropertyMapTable();
            this.PopulateStandAloneSigTable();
            this.PopulateTypeDefTable();
            this.PopulateTypeRefTable();
            this.PopulateTypeSpecTable();
            this.PopulateGuidTable();
            this.PopulateAssemblyRefTable();
            this.writer.BlobHeap = (MemoryStream)this.blobHeap.BaseStream; //this.blobHeap = null;
            this.writer.SdataHeap = (MemoryStream)this.sdataHeap.BaseStream; //this.sdataHeap = null;
            this.writer.TlsHeap = (MemoryStream)this.tlsHeap.BaseStream; //this.tlsHeap = null;
            this.writer.StringHeap = (MemoryStream)this.stringHeap.BaseStream; //this.stringHeap = null;
            this.writer.UserstringHeap = (MemoryStream)this.userStringHeap.BaseStream; //this.userStringHeap = null;
            this.writer.MethodBodiesHeap = (MemoryStream)this.methodBodiesHeap.BaseStream; //this.methodBodiesHeap = null;
            this.writer.ResourceDataHeap = (MemoryStream)this.resourceDataHeap.BaseStream; //this.resourceDataHeap = null;
            this.writer.Win32Resources = this.module.Win32Resources;
        }
        int GetAssemblyRefIndex(AssemblyNode/*!*/ assembly)
        {
            if (assembly.Location == "unknown:location")
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
                  ExceptionStrings.UnresolvedAssemblyReferenceNotAllowed, assembly.Name));
            Object index = this.assemblyRefIndex[assembly.UniqueKey];
            if (index == null)
            {
                index = this.assemblyRefEntries.Count + 1;
                AssemblyReference aref = new AssemblyReference(assembly);
                if (this.module.UsePublicKeyTokensForAssemblyReferences)
                {
                    aref.PublicKeyOrToken = aref.PublicKeyToken;
                    aref.HashValue = null;
                    aref.Flags = aref.Flags & ~AssemblyFlags.PublicKey;
                }
                this.assemblyRefEntries.Add(aref);
                this.assemblyRefIndex[assembly.UniqueKey] = index;
            }
            return (int)index;
        }
        int GetBlobIndex(ExpressionList expressions, ParameterList parameters)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            this.WriteCustomAttributeSignature(expressions, parameters, false, signature);
            byte[] sigBytes = sig.ToArray();
            int length = sigBytes.Length;
            int index = (int)this.blobHeap.BaseStream.Position;
            Ir2md.WriteCompressedInt(this.blobHeap, length);
            this.blobHeap.BaseStream.Write(sigBytes, 0, length);
            return index;
        }
        void WriteCustomAttributeSignature(ExpressionList expressions, ParameterList parameters, bool onlyWriteNamedArguments, BinaryWriter signature)
        {
            int n = parameters == null ? 0 : parameters.Count;
            int m = expressions == null ? 0 : expressions.Count;
            Debug.Assert(m >= n);
            int numNamed = m > n ? m - n : 0;
            if (onlyWriteNamedArguments)
            {
                Ir2md.WriteCompressedInt(signature, numNamed);
            }
            else
            {
                signature.Write((short)1);
                if (parameters != null && expressions != null)
                {
                    for (int i = 0; i < n; i++)
                    {
                        Parameter p = parameters[i];
                        Expression e = expressions[i];
                        if (p == null || e == null) continue;
                        Literal l = e as Literal;
                        if (l == null) { Debug.Assert(false); continue; }
                        this.WriteCustomAttributeLiteral(signature, l, p.Type == CoreSystemTypes.Object);
                    }
                }
                signature.Write((short)numNamed);
            }
            if (expressions != null)
            {
                for (int i = n; i < m; i++)
                {
                    Expression e = expressions[i];
                    NamedArgument narg = e as NamedArgument;
                    if (narg == null) { Debug.Assert(false); continue; }
                    signature.Write((byte)(narg.IsCustomAttributeProperty ? 0x54 : 0x53));
                    if (narg.ValueIsBoxed)
                        signature.Write((byte)ElementType.BoxedEnum);
                    else if (narg.Value.Type is EnumNode)
                    {
                        signature.Write((byte)ElementType.Enum);
                        this.WriteSerializedTypeName(signature, narg.Value.Type);
                    }
                    else if (narg.Value.Type == CoreSystemTypes.Type)
                        signature.Write((byte)ElementType.Type);
                    else if (narg.Value.Type is ArrayType)
                    {
                        ArrayType arrT = (ArrayType)narg.Value.Type;
                        if (arrT.ElementType == CoreSystemTypes.Type)
                        {
                            signature.Write((byte)ElementType.SzArray);
                            signature.Write((byte)ElementType.Type);
                        }
                        else
                            this.WriteTypeSignature(signature, narg.Value.Type);
                    }
                    else
                        this.WriteTypeSignature(signature, narg.Value.Type);
                    signature.Write(narg.Name.Name, false);
                    this.WriteCustomAttributeLiteral(signature, (Literal)narg.Value, narg.ValueIsBoxed);
                }
            }
        }
        int GetBlobIndex(byte[]/*!*/ blob)
        {
            object indexOb = this.blobHeapIndex[blob];
            if (indexOb != null) return (int)indexOb;
            int index = (int)this.blobHeap.BaseStream.Position;
            int length = blob.Length;
            Ir2md.WriteCompressedInt(this.blobHeap, length);
            this.blobHeap.BaseStream.Write(blob, 0, length);
            this.blobHeapIndex[blob] = index;
            return index;
        }
        int GetBlobIndex(string/*!*/ str)
        {
            object indexOb = this.blobHeapStringIndex[str];
            if (indexOb != null) return (int)indexOb;
            int index = (int)this.blobHeap.BaseStream.Position;
            this.blobHeap.Write((string)str);
            this.blobHeapStringIndex[str] = index;
            return index;
        }
        int GetBlobIndex(Field/*!*/ field)
        {
            if (field != null && field.DeclaringType != null && field.DeclaringType.Template != null && field.DeclaringType.Template.IsGeneric)
                field = this.GetUnspecializedField(field);
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            signature.Write((byte)0x6);
            TypeNode fieldType = field.Type;
#if ExtendedRuntime
      if (field.HasOutOfBandContract) fieldType = TypeNode.DeepStripModifiers(fieldType, null, SystemTypes.NonNullType);
#endif
            if (fieldType == null) { Debug.Fail(""); fieldType = SystemTypes.Object; }
            this.WriteTypeSignature(signature, fieldType, true);
            return this.GetBlobIndex(sig.ToArray());
        }
        int GetBlobIndex(MarshallingInformation/*!*/ marshallingInformation)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            signature.Write((byte)marshallingInformation.NativeType);
            switch (marshallingInformation.NativeType)
            {
                case NativeType.SafeArray:
                    signature.Write((byte)marshallingInformation.ElementType);
                    if (marshallingInformation.Class != null && marshallingInformation.Class.Length > 0)
                        signature.Write(marshallingInformation.Class, false);
                    break;
                case NativeType.LPArray:
                    signature.Write((byte)marshallingInformation.ElementType);
                    if (marshallingInformation.ParamIndex >= 0 || marshallingInformation.ElementSize > 0)
                    {
                        if (marshallingInformation.ParamIndex < 0)
                        {
                            Debug.Fail("MarshallingInformation.ElementSize > 0 should imply that ParamIndex >= 0");
                            marshallingInformation.ParamIndex = 0;
                        }
                        Ir2md.WriteCompressedInt(signature, marshallingInformation.ParamIndex);
                    }
                    if (marshallingInformation.ElementSize > 0)
                    {
                        Ir2md.WriteCompressedInt(signature, marshallingInformation.ElementSize);
                        if (marshallingInformation.NumberOfElements > 0)
                            Ir2md.WriteCompressedInt(signature, marshallingInformation.NumberOfElements);
                    }
                    break;
                case NativeType.ByValArray:
                    Ir2md.WriteCompressedInt(signature, marshallingInformation.Size);
                    if (marshallingInformation.ElementType != NativeType.NotSpecified)
                        signature.Write((byte)marshallingInformation.ElementType);
                    break;
                case NativeType.ByValTStr:
                    Ir2md.WriteCompressedInt(signature, marshallingInformation.Size);
                    break;
                case NativeType.CustomMarshaler:
                    signature.Write((short)0);
                    signature.Write(marshallingInformation.Class);
                    signature.Write(marshallingInformation.Cookie);
                    break;
            }
            return this.GetBlobIndex(sig.ToArray());
        }
        int GetBlobIndex(Literal/*!*/ literal)
        {
            int index = (int)this.blobHeap.BaseStream.Position;
            TypeNode lType = literal.Type;
            EnumNode eType = lType as EnumNode;
            if (eType != null) lType = eType.UnderlyingType;
            IConvertible ic = literal.Value as IConvertible;
            if (ic == null) ic = "";
            switch (lType.typeCode)
            {
                case ElementType.Boolean: this.blobHeap.Write((byte)1); this.blobHeap.Write(ic.ToBoolean(null)); break;
                case ElementType.Char: this.blobHeap.Write((byte)2); this.blobHeap.Write(ic.ToChar(null)); break;
                case ElementType.Int8: this.blobHeap.Write((byte)1); this.blobHeap.Write(ic.ToSByte(null)); break;
                case ElementType.UInt8: this.blobHeap.Write((byte)1); this.blobHeap.Write(ic.ToByte(null)); break;
                case ElementType.Int16: this.blobHeap.Write((byte)2); this.blobHeap.Write(ic.ToInt16(null)); break;
                case ElementType.UInt16: this.blobHeap.Write((byte)2); this.blobHeap.Write(ic.ToUInt16(null)); break;
                case ElementType.Int32: this.blobHeap.Write((byte)4); this.blobHeap.Write(ic.ToInt32(null)); break;
                case ElementType.UInt32: this.blobHeap.Write((byte)4); this.blobHeap.Write(ic.ToUInt32(null)); break;
                case ElementType.Int64: this.blobHeap.Write((byte)8); this.blobHeap.Write(ic.ToInt64(null)); break;
                case ElementType.UInt64: this.blobHeap.Write((byte)8); this.blobHeap.Write(ic.ToUInt64(null)); break;
                case ElementType.Single: this.blobHeap.Write((byte)4); this.blobHeap.Write(ic.ToSingle(null)); break;
                case ElementType.Double: this.blobHeap.Write((byte)8); this.blobHeap.Write(ic.ToDouble(null)); break;
                case ElementType.String: this.blobHeap.Write((string)literal.Value, false); break;
                case ElementType.Array:
                case ElementType.Class:
                case ElementType.Object:
                case ElementType.Reference:
                case ElementType.SzArray: this.blobHeap.Write((byte)4); this.blobHeap.Write((int)0); break; //REVIEW: standard implies this should be 0, peverify thinks otherwise.
                default: Debug.Assert(false, "Unexpected Literal type"); return 0;
            }
            return index;
        }
        int GetBlobIndex(FunctionPointer/*!*/ fp)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            this.WriteMethodSignature(signature, fp);
            return this.GetBlobIndex(sig.ToArray());
        }
        int GetBlobIndex(Method/*!*/ method, bool methodSpecSignature)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            if (methodSpecSignature)
                this.WriteMethodSpecSignature(signature, method);
            else
                this.WriteMethodSignature(signature, method);
            return this.GetBlobIndex(sig.ToArray());
        }
        int GetBlobIndex(AttributeList/*!*/ securityAttributes)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            signature.Write((byte)'.');
            Ir2md.WriteCompressedInt(signature, securityAttributes.Count);
            foreach (AttributeNode attr in securityAttributes)
                this.WriteSecurityAttribute(signature, attr);
            return this.GetBlobIndex(sig.ToArray());
        }
        private void WriteSecurityAttribute(BinaryWriter signature, AttributeNode attr)
        {
            this.WriteSerializedTypeName(signature, attr.Type);
            MemoryStream sig = new MemoryStream();
            BinaryWriter casig = new BinaryWriter(sig);
            MemberBinding mb = attr.Constructor as MemberBinding;
            if (mb == null) return;
            InstanceInitializer constructor = mb.BoundMember as InstanceInitializer;
            if (constructor == null) return;
            this.WriteCustomAttributeSignature(attr.Expressions, constructor.Parameters, true, casig);
            byte[] sigBytes = sig.ToArray();
            int length = sigBytes.Length;
            Ir2md.WriteCompressedInt(signature, length);
            signature.BaseStream.Write(sigBytes, 0, length);
        }
        int GetBlobIndex(Property/*!*/ prop)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            this.WritePropertySignature(signature, prop);
            return this.GetBlobIndex(sig.ToArray());
        }
        int GetBlobIndex(TypeNode/*!*/ type)
        {
            MemoryStream sig = new MemoryStream();
            BinaryWriter signature = new BinaryWriter(sig);
            this.WriteTypeSignature(signature, type, true);
            return this.GetBlobIndex(sig.ToArray());
        }
        int GetCustomAttributeParentCodedIndex(Node/*!*/ node)
        {
            switch (node.NodeType)
            {
                case NodeType.InstanceInitializer:
                case NodeType.StaticInitializer:
                case NodeType.Method: return this.GetMethodIndex((Method)node) << 5;
                case NodeType.Field: return (this.GetFieldIndex((Field)node) << 5) | 1;
                case NodeType.Parameter: return (this.GetParamIndex((Parameter)node) << 5) | 4;
                case NodeType.Class:
                case NodeType.DelegateNode:
                case NodeType.EnumNode:
                case NodeType.Interface:
                case NodeType.Struct:
#if !MinimalReader
                case NodeType.TupleType:
                case NodeType.TypeAlias:
                case NodeType.TypeIntersection:
                case NodeType.TypeUnion:
#endif
                    TypeNode t = (TypeNode)node;
                    if (this.IsStructural(t) && (!t.IsGeneric || (t.Template != null && t.ConsolidatedTemplateArguments != null && t.ConsolidatedTemplateArguments.Count > 0)))
                        return (this.GetTypeSpecIndex(t) << 5) | 13;
                    else
                        return (this.GetTypeDefIndex(t) << 5) | 3;
                case NodeType.ClassParameter:
                case NodeType.TypeParameter:
                    if (!this.UseGenerics) goto case NodeType.Class;
                    return (this.GetGenericParamIndex((TypeNode)node) << 5) | 19;
                case NodeType.Property: return (this.GetPropertyIndex((Property)node) << 5) | 9;
                case NodeType.Event: return (this.GetEventIndex((Event)node) << 5) | 10;
                case NodeType.Module: return (1 << 5) | 7;
                case NodeType.Assembly: return (1 << 5) | 14;
                default: Debug.Assert(false, "Unexpect custom attribute parent"); return 0;
            }
        }
#if !ROTOR
        ISymUnmanagedDocumentWriter GetDocumentWriter(Document/*!*/ doc)
        //^ requires this.symWriter != null;
        {
            int key = Identifier.For(doc.Name).UniqueIdKey;
            object writer = this.documentMap[key];
            if (writer == null)
            {
                writer = this.symWriter.DefineDocument(doc.Name, ref doc.Language, ref doc.LanguageVendor, ref doc.DocumentType);
                this.documentMap[key] = writer;
            }
            return (ISymUnmanagedDocumentWriter)writer;
        }
#endif
        int GetEventIndex(Event/*!*/ e)
        {
            return (int)this.eventIndex[e.UniqueKey];
        }
        int GetFieldIndex(Field/*!*/ f)
        {
            Object index = this.fieldIndex[f.UniqueKey];
            if (index == null)
            {
                if (this.fieldEntries == null) return 1;
                index = this.fieldEntries.Count + 1;
                this.fieldEntries.Add(f);
                this.fieldIndex[f.UniqueKey] = index;
                if (f.DefaultValue != null && !(f.DefaultValue.Value is Parameter))
                    this.constantTableEntries.Add(f);
                if (!f.IsStatic && f.DeclaringType != null && (f.DeclaringType.Flags & TypeFlags.ExplicitLayout) != 0)
                    this.fieldLayoutEntries.Add(f);
                if ((f.Flags & FieldFlags.HasFieldRVA) != 0)
                    this.fieldRvaEntries.Add(f);
                if (f.MarshallingInformation != null)
                    this.marshalEntries.Add(f);
            }
            return (int)index;
        }
        int GetGenericParamIndex(TypeNode/*!*/ gp)
        {
            return (int)this.genericParamIndex[gp.UniqueKey];
        }
        int GetFieldToken(Field/*!*/ f)
        {
            if (f.DeclaringType == null || (f.DeclaringType.DeclaringModule == this.module && !this.IsStructural(f.DeclaringType)))
                return 0x04000000 | this.GetFieldIndex(f);
            else
                return 0x0a000000 | this.GetMemberRefIndex(f);
        }
        bool IsStructural(TypeNode type)
        {
            if (type == null) return false;
            if (this.UseGenerics && (type.IsGeneric || type.Template != null && type.Template.IsGeneric)) return true;
            switch (type.NodeType)
            {
                case NodeType.ArrayType:
                case NodeType.Pointer:
                case NodeType.Reference:
                case NodeType.OptionalModifier:
                case NodeType.RequiredModifier:
                    return true;
                case NodeType.ClassParameter:
                case NodeType.TypeParameter:
                    return this.UseGenerics;
            }
            return false;
        }
        int GetFileTableIndex(Module/*!*/ module)
        {
            Object index = this.fileTableIndex[module];
            if (index == null)
            {
                index = this.fileTableEntries.Count + 1;
                this.fileTableEntries.Add(module);
                this.fileTableIndex[module] = index;
            }
            return (int)index;
        }
        int GetGuidIndex(Guid guid)
        {
            Object index = this.guidIndex[guid];
            if (index == null)
            {
                index = this.guidEntries.Count + 1;
                this.guidEntries.Add(guid);
                this.guidIndex[guid] = index;
            }
            return (int)index;
        }
        internal int GetLocalVarIndex(Local/*!*/ loc)
        {
#if !MinimalReader
            LocalBinding lb = loc as LocalBinding;
            if (lb != null) loc = lb.BoundLocal;
#endif
            if (this.StripOptionalModifiersFromLocals)
                loc.Type = TypeNode.StripModifiers(loc.Type);
            MethodInfo methInfo = this.methodInfo;

            if (methInfo.localVarSignature == null)
            {
                methInfo.localVarSignature = new BinaryWriter(new MemoryStream());
                methInfo.localVarSignature.Write((short)0);
                methInfo.localVarIndex = new TrivialHashtable();
                methInfo.localVarSigTok = 0x11000000 | this.GetStandAloneSignatureIndex(methInfo.localVarSignature);
            }
            object index = methInfo.localVarIndex[loc.UniqueKey];
            if (index == null)
            {
                methInfo.localVarIndex[loc.UniqueKey] = index = methInfo.localVarIndex.Count;
#if !ROTOR
                int startPosition = 0;
                if (this.symWriter != null && loc.Name != null && loc.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
                {
                    methInfo.debugLocals.Add(loc);
                    methInfo.signatureOffsets.Add(startPosition = methInfo.localVarSignature.BaseStream.Position);
                    if (loc.Pinned) methInfo.localVarSignature.Write((byte)ElementType.Pinned);
                    this.WriteTypeSignature(methInfo.localVarSignature, loc.Type, true);
                    methInfo.signatureLengths.Add(methInfo.localVarSignature.BaseStream.Position - startPosition);
                }
                else
                {
#endif
                    if (loc.Pinned) methInfo.localVarSignature.Write((byte)ElementType.Pinned);
                    this.WriteTypeSignature(methInfo.localVarSignature, loc.Type, true);
#if !ROTOR
                }
#endif
            }
            return (int)index;
        }
        int GetMemberRefParentEncoded(TypeNode type)
        {
            if (type == null) return 0;
            if (this.IsStructural(type)) return (this.GetTypeSpecIndex(type) << 3) | 4;
            if (type.DeclaringModule == this.module) return this.GetTypeDefIndex(type) << 3;
            if (type.DeclaringModule != null) return (this.GetTypeRefIndex(type) << 3) | 1;
            if (type.typeCode == ElementType.Class || type.typeCode == ElementType.ValueType)
                return this.GetTypeDefIndex(type) << 3; //REVIEW: when does this happen?
            Debug.Assert(false);
            return 0;
        }
        int GetMemberRefIndex(Member/*!*/ m)
        {
            Object index = this.memberRefIndex[m.UniqueKey];
            if (index == null)
            {
                index = this.memberRefEntries.Count + 1;
                this.memberRefEntries.Add(m);
                this.memberRefIndex[m.UniqueKey] = index;
                TypeNode type = m.DeclaringType;
                this.VisitReferencedType(type);
            }
            return (int)index;
        }
        class VarargMethodCallSignature : FunctionPointer
        {
            internal Method method;
            internal VarargMethodCallSignature(Method/*!*/ method, TypeNodeList/*!*/ parameterTypes)
                : base(parameterTypes, method.ReturnType, method.Name)
            {
                this.method = method;
                this.DeclaringType = method.DeclaringType;
            }
        }
        int GetMemberRefToken(Method/*!*/ m, ExpressionList arguments)
        {
            int numArgs = arguments == null ? 0 : arguments.Count;
            TypeNodeList parTypes = new TypeNodeList(numArgs);
            int varArgStart = m.Parameters.Count;
            for (int i = 0; i < varArgStart; i++)
                parTypes.Add(m.Parameters[i].Type);
            for (int i = varArgStart; i < numArgs; i++)
            {
                //^ assert arguments != null;
                parTypes.Add(arguments[i].Type);
            }
            VarargMethodCallSignature sig = new VarargMethodCallSignature(m, parTypes);
            sig.VarArgStart = varArgStart;
            sig.CallingConvention = m.CallingConvention;
            return 0x0a000000 | this.GetMemberRefIndex(sig);
        }
        int GetMethodDefOrRefEncoded(Method/*!*/ m)
        {
            if (m.DeclaringType.DeclaringModule == this.module && !this.IsStructural(m.DeclaringType))
                return this.GetMethodIndex(m) << 1;
            else
                return (this.GetMemberRefIndex(m) << 1) | 0x1;
        }
        int GetMethodIndex(Method/*!*/ m)
        {
            Object index = this.methodIndex[m.UniqueKey];
            if (index == null)
            {
                if (this.methodEntries == null) return 1;
                index = this.methodEntries.Count + 1;
                this.methodEntries.Add(m);
                this.methodIndex[m.UniqueKey] = index;
                if (m.ReturnTypeMarshallingInformation != null || (m.ReturnAttributes != null && m.ReturnAttributes.Count > 0))
                {
                    Parameter p = new Parameter();
                    p.ParameterListIndex = -1;
                    p.Attributes = m.ReturnAttributes;
                    if (m.ReturnTypeMarshallingInformation != null)
                    {
                        p.MarshallingInformation = m.ReturnTypeMarshallingInformation;
                        p.Flags = ParameterFlags.HasFieldMarshal;
                        this.marshalEntries.Add(p);
                    }
                    this.paramEntries.Add(p);
                    this.paramIndex[m.UniqueKey] = this.paramEntries.Count;
                    this.paramIndex[p.UniqueKey] = this.paramEntries.Count;
                    this.VisitAttributeList(p.Attributes, p);
                }
                int offset = m.IsStatic ? 0 : 1;
                if (m.Parameters != null)
                {
                    for (int i = 0, n = m.Parameters.Count; i < n; i++)
                    {
                        Parameter p = m.Parameters[i];
                        if (p == null) continue;
                        if (p == null) continue;
                        if (p.DeclaringMethod == null) p.DeclaringMethod = m;
                        p.ParameterListIndex = i;
                        p.ArgumentListIndex = i + offset;
                        int j = this.paramEntries.Count + 1;
                        this.paramEntries.Add(p); //TODO: provide a way to suppress the param table entries unless param has custom attributes or flags
                        this.paramIndex[p.UniqueKey] = j;
                        if (p.DefaultValue != null)
                            this.constantTableEntries.Add(p);
                        if (p.MarshallingInformation != null)
                            this.marshalEntries.Add(p);
                    }
                }
                if (m.IsGeneric)
                    this.VisitGenericParameterList(m, m.TemplateParameters);
            }
            return (int)index;
        }
        int GetMethodSpecIndex(Method/*!*/ m)
        {
            int structuralKey = m.UniqueKey;
            int blobIndex = this.GetBlobIndex(m, true);
            if (m.Template != null)
                structuralKey = (m.Template.UniqueKey << 8) + blobIndex;
            else
                Debug.Assert(false);
            Object index = this.methodSpecIndex[m.UniqueKey];
            if (index == null)
            {
                index = this.methodSpecIndex[structuralKey];
                if (index is int)
                {
                    Method otherMethod = this.methodSpecEntries[((int)index) - 1];
                    if (otherMethod != null && otherMethod.Template == m.Template && blobIndex == this.GetBlobIndex(otherMethod, true))
                        return (int)index;
                }
                index = this.methodSpecEntries.Count + 1;
                this.methodSpecEntries.Add(m);
                this.methodSpecIndex[m.UniqueKey] = index;
                this.methodSpecIndex[structuralKey] = index;
                this.GetMemberRefIndex(m.Template);
                Method templ = m.Template;
                if (templ != null)
                {
                    while (templ.Template != null) templ = templ.Template;
                    TypeNodeList templParams = templ.TemplateParameters;
                    if (templParams != null)
                    {
                        for (int i = 0, n = templParams.Count; i < n; i++)
                        {
                            TypeNode templParam = templParams[i];
                            if (templParam == null) continue;
                            this.typeParameterNumber[templParam.UniqueKey] = -(i + 1);
                        }
                    }
                }
            }
            return (int)index;
        }
        int GetMethodToken(Method/*!*/ m)
        {
            if (this.UseGenerics && m.Template != null && m.Template.IsGeneric)
                return 0x2b000000 | this.GetMethodSpecIndex(m);
            else if (m.DeclaringType.DeclaringModule == this.module && !this.IsStructural(m.DeclaringType))
                return 0x06000000 | this.GetMethodIndex(m);
            else
                return 0x0a000000 | this.GetMemberRefIndex(m);
        }
        int GetMethodDefToken(Method/*!*/ m)
        {
            if (m.DeclaringType.DeclaringModule == this.module)
                return 0x06000000 | this.GetMethodIndex(m);
            else
                return 0x0a000000 | this.GetMemberRefIndex(m);
        }
        int GetMethodBodiesHeapIndex(Method/*!*/ m)
        {
            return (int)this.methodBodiesHeapIndex[m.UniqueKey];
        }
        int GetModuleRefIndex(Module/*!*/ module)
        {
            if (module.Location == "unknown:location") throw new InvalidOperationException(ExceptionStrings.UnresolvedModuleReferenceNotAllowed);
            Object index = this.moduleRefIndex[module.Name];
            if (index == null)
            {
                index = this.moduleRefEntries.Count + 1;
                this.moduleRefEntries.Add(new ModuleReference(module.Name, module));
                this.moduleRefIndex[module.Name] = index;
                if (module.HashValue != null && module.HashValue.Length > 0)
                    this.GetFileTableIndex(module);
            }
            return (int)index;
        }
        int GetOffset(Block target, int addressOfNextInstruction)
        {
            if (target == null) return 0;
            int fixupLocation = (int)(this.methodBodyHeap.BaseStream.Position);
            Object ob = this.methodInfo.fixupIndex[target.UniqueKey];
            if (ob is int) return ((int)ob) - addressOfNextInstruction;
            Fixup fixup = new Fixup();
            fixup.addressOfNextInstruction = addressOfNextInstruction;
            fixup.fixupLocation = fixupLocation;
            fixup.shortOffset = false;
            fixup.nextFixUp = (Fixup)ob;
            this.methodInfo.fixupIndex[target.UniqueKey] = fixup;
            return 0;
        }
        int GetOffset(Block target, ref bool shortOffset)
        {
            if (target == null) return 0;
            int fixupLocation = (int)(this.methodBodyHeap.BaseStream.Position + 1);
            Object ob = this.methodInfo.fixupIndex[target.UniqueKey];
            if (ob is int)
            {
                int targetAddress = (int)ob;
                int offset = targetAddress - (fixupLocation + 1);
                if (-128 > offset || offset > 127)
                {
                    offset = targetAddress - (fixupLocation + 4);
                    Debug.Assert(offset < -128, "Forward short branch out of range");
                    shortOffset = false;
                }
                else
                    shortOffset = true;
                return offset;
            }
            Fixup fixup = new Fixup();
            fixup.fixupLocation = fixup.addressOfNextInstruction = fixupLocation;
            if (shortOffset) fixup.addressOfNextInstruction += 1; else fixup.addressOfNextInstruction += 4;
            fixup.shortOffset = shortOffset;
            fixup.nextFixUp = (Fixup)ob;
            this.methodInfo.fixupIndex[target.UniqueKey] = fixup;
            return 0;
        }
        int GetParamIndex(Parameter p)
        {
            if (p == null) return 0;
#if !MinimalReader
            ParameterBinding pb = p as ParameterBinding;
            if (pb != null) p = pb.BoundParameter;
#endif
            return (int)this.paramIndex[p.UniqueKey];
        }
        int GetPropertyIndex(Property/*!*/ p)
        {
            return (int)this.propertyIndex[p.UniqueKey];
        }
        int GetSecurityAttributeParentCodedIndex(Node/*!*/ node)
        {
            switch (node.NodeType)
            {
                case NodeType.InstanceInitializer:
                case NodeType.StaticInitializer:
                case NodeType.Method: return (this.GetMethodIndex((Method)node) << 2) | 1;
                case NodeType.Class:
                case NodeType.Interface:
                case NodeType.DelegateNode:
                case NodeType.EnumNode:
                case NodeType.Struct: return (this.GetTypeDefIndex((TypeNode)node) << 2) | 0;
                case NodeType.Assembly: return (1 << 2) | 2;
                default: Debug.Assert(false, "Unexpected security attribute parent"); return 0;
            }
        }
        int GetStandAloneSignatureIndex(BinaryWriter signatureWriter)
        {
            this.standAloneSignatureEntries.Add(signatureWriter);
            return this.standAloneSignatureEntries.Count;
        }
        int GetStaticDataIndex(byte[] data, PESection targetSection)
        {
            int result = 0;
            switch (targetSection)
            {
                case PESection.SData:
                    result = (int)this.sdataHeap.BaseStream.Position;
                    this.sdataHeap.Write(data);
                    break;
                case PESection.Text:
                    result = (int)this.methodBodiesHeap.BaseStream.Position;
                    this.methodBodiesHeap.Write(data);
                    break;
                case PESection.TLS:
                    result = (int)this.tlsHeap.BaseStream.Position;
                    this.tlsHeap.Write(data);
                    break;
            }
            return result;
        }
        int GetResourceDataIndex(byte[]/*!*/ data)
        {
            int index = (int)this.resourceDataHeap.BaseStream.Position;
            this.resourceDataHeap.Write((int)data.Length);
            this.resourceDataHeap.Write(data);
            return index;
        }
        int GetStringIndex(string str)
        {
            if (str == null || str.Length == 0) return 0;
            Object index = this.stringHeapIndex[str];
            if (index == null)
            {
                index = (int)this.stringHeap.BaseStream.Position;
                this.stringHeap.Write(str, true);
                this.stringHeapIndex[str] = index;
            }
            return (int)index;
        }
        int GetUserStringIndex(string/*!*/ str)
        {
            Object index = this.userStringHeapIndex[str];
            if (index == null)
            {
                index = (int)this.userStringHeap.BaseStream.Position;
                Ir2md.WriteCompressedInt(this.userStringHeap, str.Length * 2 + 1);
                this.userStringHeap.Write(str.ToCharArray());
                this.userStringHeapIndex[str] = index;
                //Write out a trailing byte indicating if the string is really quite simple
                ulong stringKind = 0; //no funny business
                foreach (char ch in str)
                {
                    if (ch >= 0x7F) stringKind += 1;
                    else
                        switch ((int)ch)
                        {
                            case 0x1:
                            case 0x2:
                            case 0x3:
                            case 0x4:
                            case 0x5:
                            case 0x6:
                            case 0x7:
                            case 0x8:
                            case 0xE:
                            case 0xF:
                            case 0x10:
                            case 0x11:
                            case 0x12:
                            case 0x13:
                            case 0x14:
                            case 0x15:
                            case 0x16:
                            case 0x17:
                            case 0x18:
                            case 0x19:
                            case 0x1A:
                            case 0x1B:
                            case 0x1C:
                            case 0x1D:
                            case 0x1E:
                            case 0x1F:
                            case 0x27:
                            case 0x2D:
                                stringKind += 1;
                                break;
                            default:
                                break;
                        }
                }
                if (stringKind > 0) stringKind = 1;
                this.userStringHeap.Write((byte)stringKind);
            }
            return (int)index;
        }
        int GetTypeDefIndex(TypeNode/*!*/ type)
        {
            Object index = this.typeDefIndex[type.UniqueKey];
            if (index == null)
            {
                if (this.typeDefEntries == null) return 0;
                index = this.typeDefEntries.Count + 1;
                this.typeDefEntries.Add(type);
                this.typeDefIndex[type.UniqueKey] = index;
                if (type.IsGeneric && type.Template == null)
                    this.VisitGenericParameterList(type, type.ConsolidatedTemplateParameters);
            }
            return (int)index;
        }
        int GetTypeDefOrRefOrSpecEncoded(TypeNode type)
        {
            if (type == null) return 0;
            if (!this.UseGenerics)
            {
                ClassParameter cp = type as ClassParameter;
                if (cp != null) { Debug.Assert(!cp.IsGeneric); return this.GetTypeDefOrRefOrSpecEncoded(cp.BaseClass); } //REVIEW: why???
            }
            if (this.IsStructural(type)) return (this.GetTypeSpecIndex(type) << 2) | 2;
            if (type.DeclaringModule == this.module) return this.GetTypeDefIndex(type) << 2;
            return (this.GetTypeRefIndex(type) << 2) | 1;
        }
        int GetTypeToken(TypeNode/*!*/ type)
        {
            if (this.IsStructural(type) && (!type.IsGeneric || (type.ConsolidatedTemplateArguments != null && type.ConsolidatedTemplateArguments.Count > 0)))
                return 0x1b000000 | this.GetTypeSpecIndex(type);
            if (type.IsGeneric)
            {
                TypeNode foundType = type.GetTemplateInstance(type, type.TemplateParameters);
                Debug.Assert(foundType != type);
                return this.GetTypeToken(foundType);
            }
            if (type.DeclaringModule == this.module)
                return 0x02000000 | this.GetTypeDefIndex(type);
            else if (type.DeclaringModule != null)
                return 0x01000000 | this.GetTypeRefIndex(type);
            else if (type.typeCode == ElementType.ValueType || type.typeCode == ElementType.Class)
            {
                type.DeclaringModule = this.module;
                return 0x02000000 | this.GetTypeDefIndex(type);
            }
            Debug.Assert(false);
            return 0;
        }
        int GetTypeDefToken(TypeNode/*!*/ type)
        {
            if (this.IsStructural(type) && (!type.IsGeneric || (type.Template != null && type.ConsolidatedTemplateArguments != null && type.ConsolidatedTemplateArguments.Count > 0)))
                return 0x1b000000 | this.GetTypeSpecIndex(type);
            if (type.DeclaringModule == this.module)
                return 0x02000000 | this.GetTypeDefIndex(type);
            else if (type.DeclaringModule != null)
                return 0x01000000 | this.GetTypeRefIndex(type);
            else if (type.typeCode == ElementType.ValueType || type.typeCode == ElementType.Class)
            {
                type.DeclaringModule = this.module;
                return 0x02000000 | this.GetTypeDefIndex(type);
            }
            Debug.Assert(false);
            return 0;
        }
        int GetTypeRefIndex(TypeNode/*!*/ type)
        {
            Object index = this.typeRefIndex[type.UniqueKey];
            if (index == null)
            {
                index = this.typeRefEntries.Count + 1;
                this.typeRefEntries.Add(type);
                this.typeRefIndex[type.UniqueKey] = index;
                Module module = type.DeclaringModule;
                AssemblyNode assembly = module as AssemblyNode;
                if (assembly != null)
                    this.GetAssemblyRefIndex(assembly);
                else
                    this.GetModuleRefIndex(module);
                if (type.DeclaringType != null)
                    this.GetTypeRefIndex(type.DeclaringType);
            }
            return (int)index;
        }
        int GetTypeSpecIndex(TypeNode/*!*/ type)
        {
            int structuralKey = type.UniqueKey;
            int blobIndex = 0;
            if (type.Template != null)
            {
                blobIndex = this.GetBlobIndex(type);
                structuralKey = ((type.Template.UniqueKey << 8) & int.MaxValue) + blobIndex;
            }
            Object index = this.typeSpecIndex[type.UniqueKey];
            if (index == null)
            {
                if (type.Template != null)
                {
                    index = this.typeSpecIndex[structuralKey];
                    if (index is int)
                    {
                        TypeNode otherType = this.typeSpecEntries[((int)index) - 1];
                        if (otherType != null && otherType.Template == type.Template && blobIndex == this.GetBlobIndex(otherType))
                            return (int)index;
                    }
                }
                index = this.typeSpecEntries.Count + 1;
                this.typeSpecEntries.Add(type);
                this.typeSpecIndex[type.UniqueKey] = index;
                if (type.Template != null)
                    this.typeSpecIndex[structuralKey] = index;
                if (type.Template != null)
                {
                    if (type.Template.DeclaringModule != this.module)
                        this.GetTypeRefIndex(type.Template);
                    TypeNodeList templArgs = type.ConsolidatedTemplateArguments;
                    for (int i = 0, n = templArgs == null ? 0 : templArgs.Count; i < n; i++)
                    {
                        this.VisitReferencedType(templArgs[i]);
                    }
                }
                else
                {
                    TypeNodeList telems = type.StructuralElementTypes;
                    for (int i = 0, n = telems == null ? 0 : telems.Count; i < n; i++)
                        this.VisitReferencedType(telems[i]);
                }
            }
            return (int)index;
        }
        TrivialHashtable/*!*/ unspecializedFieldFor = new TrivialHashtable();
        Field/*!*/ GetUnspecializedField(Field/*!*/ field)
        {
            if (field == null || field.DeclaringType == null || !field.DeclaringType.IsGeneric) { Debug.Fail(""); return field; }
            Field unspecializedField = (Field)this.unspecializedFieldFor[field.UniqueKey];
            if (unspecializedField != null) return unspecializedField;
            TypeNode template = field.DeclaringType;
            if (template == null) { Debug.Assert(false); return field; }
            while (template.Template != null) template = template.Template;
            MemberList specializedMembers = field.DeclaringType.Members;
            MemberList unspecializedMembers = template.Members;
            for (int i = 0, n = specializedMembers.Count; i < n; i++)
            {
                if (specializedMembers[i] != field) continue;
                unspecializedField = (Field)unspecializedMembers[i];
                if (unspecializedField == null) { Debug.Fail(""); unspecializedField = field; }
                this.unspecializedFieldFor[field.UniqueKey] = unspecializedField;
                this.VisitReferencedType(unspecializedField.DeclaringType);
                return unspecializedField;
            }
            Debug.Fail("");
            return field;
        }
        TrivialHashtable/*!*/ unspecializedMethodFor = new TrivialHashtable();
        Method/*!*/ GetUnspecializedMethod(Method/*!*/ method)
        {
            Debug.Assert(method != null && method.DeclaringType != null && method.DeclaringType.IsGeneric);
            Method unspecializedMethod = (Method)this.unspecializedMethodFor[method.UniqueKey];
            if (unspecializedMethod != null) return unspecializedMethod;
            TypeNode template = method.DeclaringType;
            if (template == null) { Debug.Assert(false); return method; }
            while (template.Template != null) template = template.Template;
            MemberList specializedMembers = method.DeclaringType.Members;
            MemberList unspecializedMembers = template.Members;
            for (int i = 0, n = specializedMembers.Count; i < n; i++)
            {
                if (specializedMembers[i] != method) continue;
                unspecializedMethod = unspecializedMembers[i] as Method;
                if (unspecializedMethod == null) break;
                this.unspecializedMethodFor[method.UniqueKey] = unspecializedMethod;
                template = unspecializedMethod.DeclaringType;
                while (template.Template != null) template = template.Template;
                this.VisitReferencedType(template);
                for (int j = 0, m = unspecializedMethod.TemplateParameters == null ? 0 : unspecializedMethod.TemplateParameters.Count; j < m; j++)
                {
                    TypeNode p = unspecializedMethod.TemplateParameters[j];
                    if (p == null) continue;
                    this.typeParameterNumber[p.UniqueKey] = -(j + 1);
                }
                return unspecializedMethod;
            }
            Debug.Assert(false);
            return method;
        }
        internal void IncrementStackHeight()
        {
            this.stackHeight++;
            if (this.stackHeight > this.stackHeightMax) this.stackHeightMax = this.stackHeight;
        }
        void PopulateAssemblyTable()
        //^ requires this.assembly != null;
        {
            AssemblyNode assembly = this.assembly;
            AssemblyRow[] assemblyTable = this.writer.assemblyTable = new AssemblyRow[1];
            assemblyTable[0].HashAlgId = (int)AssemblyHashAlgorithm.SHA1;
            assemblyTable[0].Flags = (int)assembly.Flags;
            if (assembly.Version == null) assembly.Version = new Version(1, 0, 0, 0);
            assemblyTable[0].MajorVersion = assembly.Version.Major;
            assemblyTable[0].MinorVersion = assembly.Version.Minor;
            assemblyTable[0].RevisionNumber = assembly.Version.Revision;
            assemblyTable[0].BuildNumber = assembly.Version.Build;
            if (assembly.PublicKeyOrToken != null && 0 < assembly.PublicKeyOrToken.Length)
                assemblyTable[0].PublicKey = this.GetBlobIndex(assembly.PublicKeyOrToken);
            if (assembly.Name != null)
                assemblyTable[0].Name = this.GetStringIndex(assembly.Name);
            else
                Debug.Assert(false, "Assembly must have a name");
            if (assembly.Culture != null && assembly.Culture.Length > 0)
                assemblyTable[0].Culture = this.GetStringIndex(assembly.Culture);
            this.writer.assemblyTable = assemblyTable;
        }
        void PopulateAssemblyRefTable()
        {
            AssemblyReferenceList arList = this.module.AssemblyReferences = this.assemblyRefEntries;
            if (arList == null) return;
            int n = arList.Count;
            AssemblyRefRow[] arRows = this.writer.assemblyRefTable = new AssemblyRefRow[n];
            for (int i = 0; i < n; i++)
            {
                AssemblyReference ar = arList[i];
                if (ar.Version == null)
                    Debug.Assert(false, "assembly reference without a version");
                else
                {
                    arRows[i].MajorVersion = ar.Version.Major;
                    arRows[i].MinorVersion = ar.Version.Minor;
                    arRows[i].RevisionNumber = ar.Version.Revision;
                    arRows[i].BuildNumber = ar.Version.Build;
                    arRows[i].Flags = (int)ar.Flags;
                }
                if (ar.PublicKeyOrToken != null && 0 < ar.PublicKeyOrToken.Length)
                    arRows[i].PublicKeyOrToken = this.GetBlobIndex(ar.PublicKeyOrToken);
                if (ar.Name == null)
                    Debug.Assert(false, "assembly reference without a name");
                else
                    arRows[i].Name = this.GetStringIndex(ar.Name);
                if (ar.Culture != null && ar.Culture.Length > 0)
                    arRows[i].Culture = this.GetStringIndex(ar.Culture);
                if (ar.HashValue != null)
                    arRows[i].HashValue = this.GetBlobIndex(ar.HashValue);
            }
            //this.assemblyRefEntries = null;
        }
        void PopulateClassLayoutTable()
        {
            int n = this.classLayoutEntries.Count;
            if (n == 0) return;
            ClassLayoutRow[] clr = this.writer.classLayoutTable = new ClassLayoutRow[n];
            for (int i = 0; i < n; i++)
            {
                TypeNode t = this.classLayoutEntries[i];
                clr[i].ClassSize = t.ClassSize;
                clr[i].PackingSize = t.PackingSize;
                clr[i].Parent = this.GetTypeDefIndex(t);
            }
            //this.classLayoutEntries = null;
        }
        void PopulateConstantTable()
        {
            int n = this.constantTableEntries.Count;
            if (n == 0) return;
            ConstantRow[] cr = this.writer.constantTable = new ConstantRow[n];
            for (int i = 0; i < n; i++)
            {
                Parameter p = this.constantTableEntries[i] as Parameter;
                if (p != null)
                {
                    cr[i].Parent = (this.GetParamIndex(p) << 2) | 1;
                    cr[i].Value = this.GetBlobIndex((Literal)p.DefaultValue);
                    TypeNode t = p.DefaultValue.Type;
                    if (t.NodeType == NodeType.EnumNode) t = ((EnumNode)t).UnderlyingType;
                    cr[i].Type = (int)t.typeCode;
                    if (t is Reference || (t != p.Type && Literal.IsNullLiteral(p.DefaultValue)))
                        cr[i].Type = (int)ElementType.Class;
                }
                else
                {
                    Field f = (Field)this.constantTableEntries[i];
                    cr[i].Parent = (this.GetFieldIndex(f) << 2);
                    cr[i].Value = this.GetBlobIndex(f.DefaultValue);
                    TypeNode t = f.DefaultValue.Type;
                    if (t.NodeType == NodeType.EnumNode) t = ((EnumNode)t).UnderlyingType;
                    cr[i].Type = (int)t.typeCode;
                    if (t is Reference || (t != f.Type && Literal.IsNullLiteral(f.DefaultValue)))
                        cr[i].Type = (int)ElementType.Class;
                }
                ConstantRow temp = cr[i];
                int parent = temp.Parent;
                for (int j = i - 1; j >= 0; j--)
                {
                    if (cr[j].Parent > parent)
                    {
                        cr[j + 1] = cr[j];
                        if (j == 0)
                        {
                            cr[0] = temp;
                            break;
                        }
                    }
                    else
                    {
                        if (j < i - 1) cr[j + 1] = temp;
                        break;
                    }
                }
            }
            //TODO: more efficient sort
            //this.constantTableEntries = null;
        }
        void PopulateCustomAttributeTable()
        {
            if (this.customAttributeCount == 0) return;
            CustomAttributeRow[] table = this.writer.customAttributeTable = new CustomAttributeRow[this.customAttributeCount];
            int k = 0;
            int prevCodedIndex = 0;
            for (int i = 0, n = this.nodesWithCustomAttributes.Count; i < n; i++)
            {
                AttributeList attrs = null;
                Node node = this.nodesWithCustomAttributes[i];
                int codedIndex = 0;
                switch (node.NodeType)
                {
                    case NodeType.Method:
                    case NodeType.InstanceInitializer:
                    case NodeType.StaticInitializer:
                        Method m = (Method)node;
                        codedIndex = this.GetMethodIndex(m) << 5;
                        attrs = m.Attributes;
                        break;
                    case NodeType.Field:
                        Field f = (Field)node;
                        codedIndex = (this.GetFieldIndex(f) << 5) | 1;
                        attrs = f.Attributes;
                        break;
                    case NodeType.Parameter:
                        Parameter par = (Parameter)node;
                        codedIndex = (this.GetParamIndex(par) << 5) | 4;
                        attrs = par.Attributes;
                        break;
                    case NodeType.Class:
                    case NodeType.DelegateNode:
                    case NodeType.EnumNode:
                    case NodeType.Interface:
                    case NodeType.Struct:
#if !MinimalReader
                    case NodeType.TupleType:
                    case NodeType.TypeAlias:
                    case NodeType.TypeIntersection:
                    case NodeType.TypeUnion:
#endif
                        TypeNode t = (TypeNode)node;
                        if (this.IsStructural(t) && (!t.IsGeneric || (t.Template != null && t.ConsolidatedTemplateArguments != null && t.ConsolidatedTemplateArguments.Count > 0)))
                            codedIndex = (this.GetTypeSpecIndex(t) << 5) | 13;
                        else
                            codedIndex = (this.GetTypeDefIndex(t) << 5) | 3;
                        attrs = t.Attributes;
                        break;
                    case NodeType.ClassParameter:
                    case NodeType.TypeParameter:
                        if (!this.UseGenerics) goto case NodeType.Class;
                        t = (TypeNode)node;
                        codedIndex = (this.GetGenericParamIndex(t) << 5) | 19;
                        attrs = t.Attributes;
                        break;
                    case NodeType.Property:
                        Property p = (Property)node;
                        codedIndex = (this.GetPropertyIndex(p) << 5) | 9;
                        attrs = p.Attributes;
                        break;
                    case NodeType.Event:
                        Event e = (Event)node;
                        codedIndex = (this.GetEventIndex(e) << 5) | 10;
                        attrs = e.Attributes;
                        break;
                    case NodeType.Module:
                    case NodeType.Assembly:
                        codedIndex = (1 << 5) | (node.NodeType == NodeType.Module ? 7 : 14);
                        attrs = ((Module)node).Attributes;
                        break;
                    default:
                        Debug.Assert(false);
                        break;
                }
                if (attrs == null) continue;
                if (UseGenerics)
                {
                    Debug.Assert(codedIndex > prevCodedIndex);
                }
                prevCodedIndex = codedIndex;
                for (int j = 0, m = attrs.Count; j < m; j++)
                {
                    AttributeNode a = attrs[j];
                    if (a == null) continue;
                    table[k].Parent = codedIndex;
                    Debug.Assert(a.Constructor is MemberBinding);
                    Method cons = (Method)((MemberBinding)a.Constructor).BoundMember;
                    if (cons.DeclaringType.DeclaringModule == this.module && !this.IsStructural(cons.DeclaringType))
                        table[k].Constructor = (this.GetMethodIndex(cons) << 3) | 2;
                    else
                        table[k].Constructor = (this.GetMemberRefIndex(cons) << 3) | 3;
                    table[k].Value = this.GetBlobIndex(a.Expressions, cons.Parameters);
                    k++;
                }
            }
        }
        void PopulateDeclSecurityTable()
        {
            if (this.securityAttributeCount == 0) return;
            DeclSecurityRow[] table = this.writer.declSecurityTable = new DeclSecurityRow[this.securityAttributeCount];
            int k = 0;
            int prevCodedIndex = 0;
            for (int i = 0, n = this.nodesWithSecurityAttributes.Count; i < n; i++)
            {
                SecurityAttributeList attrs = null;
                Node node = this.nodesWithSecurityAttributes[i];
                int codedIndex = 0;
                switch (node.NodeType)
                {
                    case NodeType.Method:
                    case NodeType.InstanceInitializer:
                    case NodeType.StaticInitializer:
                        Method m = (Method)node;
                        codedIndex = (this.GetMethodIndex(m) << 2) | 1;
                        attrs = m.SecurityAttributes;
                        break;
                    case NodeType.Class:
                    case NodeType.Interface:
                    case NodeType.DelegateNode:
                    case NodeType.EnumNode:
                    case NodeType.Struct:
                        TypeNode t = (TypeNode)node;
                        codedIndex = (this.GetTypeDefIndex(t) << 2) | 0;
                        attrs = t.SecurityAttributes;
                        break;
                    case NodeType.Assembly:
                        codedIndex = (1 << 2) | 2;
                        attrs = ((AssemblyNode)node).SecurityAttributes;
                        break;
                    default:
                        Debug.Assert(false);
                        break;
                }
                if (attrs == null) continue;
                Debug.Assert(codedIndex > prevCodedIndex);
                prevCodedIndex = codedIndex;
                for (int j = 0, m = attrs.Count; j < m; j++)
                {
                    SecurityAttribute a = attrs[j];
                    if (a == null) continue;
                    this.VisitReferencedType(CoreSystemTypes.SecurityAction);
                    table[k].Action = (int)a.Action;
                    table[k].Parent = codedIndex;
                    if (CoreSystemTypes.SystemAssembly.MetadataFormatMajorVersion == 1 && CoreSystemTypes.SystemAssembly.MetadataFormatMinorVersion < 1)
                        table[k].PermissionSet = this.GetBlobIndex(a.SerializedPermissions);
                    else
                    {
                        if (a.PermissionAttributes != null)
                        {
                            table[k].PermissionSet = this.GetBlobIndex(a.PermissionAttributes);
                        }
                        else
                        {
                            // Came across some assemblies that had a metadata version > 1.0, but still used
                            // serialized security attributes. So might as well try to see if this is the case
                            // if the PermissionAttributes are null.
                            table[k].PermissionSet = this.GetBlobIndex(a.SerializedPermissions);
                        }
                    }
                    k++;
                }
            }
        }
        void PopulateEventMapTable()
        {
            int n = this.eventMapEntries.Count;
            if (n == 0) return;
            EventMapRow[] emr = this.writer.eventMapTable = new EventMapRow[n];
            for (int i = 0; i < n; i++)
            {
                Event e = this.eventMapEntries[i];
                emr[i].Parent = this.GetTypeDefIndex(e.DeclaringType);
                emr[i].EventList = this.GetEventIndex(e);
            }
            //this.eventMapEntries = null;
        }
        void PopulateEventTable()
        {
            int n = this.eventEntries.Count;
            if (n == 0) return;
            EventRow[] er = this.writer.eventTable = new EventRow[n];
            for (int i = 0; i < n; i++)
            {
                Event e = this.eventEntries[i];
                if (e == null || e.Name == null) continue;
                er[i].Flags = (int)e.Flags;
                er[i].Name = this.GetStringIndex(e.Name.ToString());
                er[i].EventType = this.GetTypeDefOrRefOrSpecEncoded(e.HandlerType);
            }
            //this.eventEntries = null;
        }
        void PopulateExportedTypeTable()
        {
            if (this.assembly == null) return;
            TypeNodeList exportedTypes = this.assembly.ExportedTypes;
            int n = exportedTypes == null ? 0 : exportedTypes.Count;
            if (n == 0) return;
            ExportedTypeRow[] ett = this.writer.exportedTypeTable = new ExportedTypeRow[n];
            for (int i = 0; i < n; i++)
            {
                TypeNode et = exportedTypes[i];
                if (et == null || et.Namespace == null || et.Name == null) continue;
                ett[i].TypeDefId = 0;
                ett[i].TypeNamespace = this.GetStringIndex(et.Namespace.ToString());
                ett[i].TypeName = this.GetStringIndex(et.Name.ToString());
                ett[i].Flags = (int)(et.Flags & TypeFlags.VisibilityMask);
                if (et.DeclaringType != null)
                {
                    for (int j = 0; j < i; j++)
                    {
                        if (exportedTypes[j] == et.DeclaringType)
                        {
                            ett[i].Implementation = (j << 2) | 2;
                            break;
                        }
                    }
                }
                else if (et.DeclaringModule != this.module && et.DeclaringModule is AssemblyNode)
                {
                    ett[i].Implementation = (this.GetAssemblyRefIndex((AssemblyNode)et.DeclaringModule) << 2) | 1;
                    ett[i].Flags = (int)TypeFlags.Forwarder;
                }
                else
                    ett[i].Implementation = (this.GetFileTableIndex(et.DeclaringModule) << 2) | 0;
            }
        }
        void PopulateFieldTable()
        {
            int n = this.fieldEntries.Count;
            if (n == 0) return;
            FieldRow[] fr = this.writer.fieldTable = new FieldRow[n];
            for (int i = 0; i < n; i++)
            {
                Field f = this.fieldEntries[i];
                fr[i].Flags = (int)f.Flags;
                fr[i].Name = this.GetStringIndex(f.Name.Name); // we don't store prefixes in field names.
                fr[i].Signature = this.GetBlobIndex(f);
            }
            //this.fieldEntries = null;
        }
        void PopulateFieldLayoutTable()
        {
            int n = this.fieldLayoutEntries.Count;
            if (n == 0) return;
            FieldLayoutRow[] flr = this.writer.fieldLayoutTable = new FieldLayoutRow[n];
            for (int i = 0; i < n; i++)
            {
                Field f = this.fieldLayoutEntries[i];
                flr[i].Field = this.GetFieldIndex(f);
                flr[i].Offset = f.Offset;
            }
            //this.fieldLayoutEntries = null;
        }
        void PopulateFieldRVATable()
        {
            int n = this.fieldRvaEntries.Count;
            if (n == 0) return;
            FieldRvaRow[] frr = this.writer.fieldRvaTable = new FieldRvaRow[n];
            for (int i = 0; i < n; i++)
            {
                Field f = this.fieldRvaEntries[i];
                frr[i].Field = this.GetFieldIndex(f);
                if (f.InitialData != null)
                    frr[i].RVA = this.GetStaticDataIndex(f.InitialData, f.Section); //Fixed up to be an RVA inside MetadataWriter.
                else
                    frr[i].RVA = f.Offset;
                frr[i].TargetSection = f.Section;
            }
            //this.fieldRvaEntries = null;
        }
        void PopulateFileTable()
        {
            int n = this.fileTableEntries.Count;
            if (n == 0) return;
            bool readContents = false;
            FileRow[] ftr = this.writer.fileTable = new FileRow[n];
            for (int i = 0; i < n; i++)
            {
                Module module = this.fileTableEntries[i];
                switch (module.Kind)
                {
                    case ModuleKindFlags.ConsoleApplication:
                    case ModuleKindFlags.DynamicallyLinkedLibrary:
                    case ModuleKindFlags.WindowsApplication:
                        ftr[i].Flags = (int)FileFlags.ContainsMetaData;
                        break;
                    case ModuleKindFlags.ManifestResourceFile:
                        readContents = true;
                        ftr[i].Flags = (int)FileFlags.ContainsNoMetaData;
                        break;
                    case ModuleKindFlags.UnmanagedDynamicallyLinkedLibrary:
                        ftr[i].Flags = (int)FileFlags.ContainsNoMetaData;
                        break;
                }
                if (module.HashValue != null)
                    ftr[i].HashValue = this.GetBlobIndex(module.HashValue);
                else
                    ftr[i].HashValue = 0;
                ftr[i].Name = this.GetStringIndex(module.Name);
                if (readContents)
                {
                    try
                    {
                        FileStream fs = File.OpenRead(module.Location);
                        long size = fs.Length;
                        byte[] buffer = new byte[size];
                        fs.Read(buffer, 0, (int)size);
                        System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
                        byte[] hash = sha1.ComputeHash(buffer);
                        ftr[i].HashValue = this.GetBlobIndex(hash);
                    }
                    catch { }
                }
            }
            //this.fileTableEntries = null;
        }
        void PopulateGuidTable()
        {
            int n = this.guidEntries.Count;
            Guid[] guids = this.writer.GuidHeap = new Guid[n];
            for (int i = 0; i < n; i++)
                guids[i] = (Guid)this.guidEntries[i];
            //this.guidEntries = null;
        }
        void PopulateGenericParamTable()
        {
            int n = this.genericParamEntries.Count;
            if (n == 0) return;
            GenericParamRow[] gpr = this.writer.genericParamTable = new GenericParamRow[n];
            Member lastMember = null;
            int number = 0;
            for (int i = 0; i < n; i++)
            {
                Member m = this.genericParamEntries[i];
                TypeNode paramType = this.genericParameters[i];
                if (paramType == null || paramType.Name == null) continue;
                Method meth = m as Method;
                TypeNode type = m as TypeNode;
                if (m != lastMember) number = 0;
                gpr[i].GenericParameter = paramType;
                gpr[i].Number = number++;
                if (type != null)
                {
                    gpr[i].Name = this.GetStringIndex(paramType.Name.ToString());
                    gpr[i].Owner = (this.GetTypeDefIndex(type) << 1) | 0;
                }
                else
                {
                    //^ assert meth != null;
                    gpr[i].Name = this.GetStringIndex(paramType.Name.ToString());
                    gpr[i].Owner = (this.GetMethodIndex(meth) << 1) | 1;
                }
                ITypeParameter tp = paramType as ITypeParameter;
                if (tp != null)
                    gpr[i].Flags = (int)tp.TypeParameterFlags;
                else
                {
                    Debug.Assert(false);
                    gpr[i].Flags = 0;
                }
                lastMember = m;
                GenericParamRow temp = gpr[i];
                int owner = temp.Owner;
                for (int j = i - 1; j >= 0; j--)
                {
                    if (gpr[j].Owner > owner)
                    {
                        gpr[j + 1] = gpr[j];
                        if (j == 0)
                        {
                            gpr[0] = temp;
                            break;
                        }
                    }
                    else
                    {
                        if (j < i - 1) gpr[j + 1] = temp;
                        break;
                    }
                }
            }
            for (int i = 0; i < n; i++)
            {
                Member genPar = gpr[i].GenericParameter;
                if (genPar == null) continue;
                this.genericParamIndex[genPar.UniqueKey] = i + 1;
            }
            for (int i = 0; i < n; i++)
            {
                Member genPar = gpr[i].GenericParameter;
                if (genPar == null) continue;
                this.VisitAttributeList(genPar.Attributes, genPar);
            }
            //this.genericParamEntries = null;
            //this.genericParameters = null;
        }
        void PopulateGenericParamConstraintTable()
        {
            int n = this.genericParamConstraintEntries.Count;
            if (n == 0) return;
            GenericParamConstraintRow[] gpcr = this.writer.genericParamConstraintTable = new GenericParamConstraintRow[n];
            TypeNode lastParameter = null;
            int paramIndex = 0;
            int constraintIndex = 0;
            int indexOffset = 0;
            for (int i = 0; i < n; i++)
            {
                TypeNode t = this.genericParamConstraintEntries[i];
                if (t != lastParameter)
                {
                    paramIndex = this.GetGenericParamIndex(t);
                    constraintIndex = 0;
                    indexOffset = 0;
                }
                gpcr[i].Param = paramIndex;
                TypeNode constraint;
                if (constraintIndex == 0 && t.BaseType != null && t.BaseType != CoreSystemTypes.Object)
                {
                    constraint = t.BaseType; indexOffset = 1;
                }
                else
                    constraint = t.Interfaces[constraintIndex - indexOffset];
                gpcr[i].Constraint = this.GetTypeDefOrRefOrSpecEncoded(constraint);
                lastParameter = t;
                constraintIndex++;
                GenericParamConstraintRow temp = gpcr[i];
                int param = temp.Param;
                for (int j = i - 1; j >= 0; j--)
                {
                    if (gpcr[j].Param > param)
                    {
                        gpcr[j + 1] = gpcr[j];
                        if (j == 0)
                        {
                            gpcr[0] = temp;
                            break;
                        }
                    }
                    else
                    {
                        if (j < i - 1) gpcr[j + 1] = temp;
                        break;
                    }
                }
            }
            //this.genericParamConstraintEntries = null;
        }
        void PopulateImplMapTable()
        {
            int n = this.implMapEntries.Count;
            if (n == 0) return;
            ImplMapRow[] imr = this.writer.implMapTable = new ImplMapRow[n];
            for (int i = 0; i < n; i++)
            {
                Method m = this.implMapEntries[i];
                imr[i].ImportName = this.GetStringIndex(m.PInvokeImportName);
                imr[i].ImportScope = this.GetModuleRefIndex(m.PInvokeModule);
                imr[i].MappingFlags = (int)m.PInvokeFlags;
                imr[i].MemberForwarded = (this.GetMethodIndex(m) << 1) | 1;
            }
            //this.implMapEntries = null;
        }
        void PopulateInterfaceImplTable()
        {
            int n = this.interfaceEntries.Count;
            if (n == 0) return;
            InterfaceImplRow[] iir = this.writer.interfaceImplTable = new InterfaceImplRow[n];
            TypeNode prevT = null;
            for (int i = 0, j = 0; i < n; i++)
            {
                TypeNode t = this.interfaceEntries[i];
                if (t == prevT)
                    j++;
                else
                {
                    j = 0;
                    prevT = t;
                }
                int ti = iir[i].Class = this.GetTypeDefIndex(t);
                Interface iface = null;
#if ExtendedRuntime
        if (t is ITypeParameter){
          int numIfaces = t.Interfaces == null ? 0 : t.Interfaces.Count;
          if (j == numIfaces)
            iface = SystemTypes.ITemplateParameter;
          else
            iface = t.Interfaces[j];
        }else
#endif
                iface = t.Interfaces[j];
                if (iface == null) { i--; continue; }
                int ii = iir[i].Interface = this.GetTypeDefOrRefOrSpecEncoded(iface);
                for (int k = 0; k < i; k++)
                { //REVIEW: is a more efficient sort worthwhile?
                    if (iir[k].Class > ti)
                    {
                        for (int kk = i; kk > k; kk--)
                        {
                            iir[kk].Class = iir[kk - 1].Class;
                            iir[kk].Interface = iir[kk - 1].Interface;
                        }
                        iir[k].Class = ti;
                        iir[k].Interface = ii;
                        break;
                    }
                }
            }
            //this.interfaceEntries = null;
        }
        void PopulateManifestResourceTable()
        {
            ResourceList resources = this.module.Resources;
            int n = resources == null ? 0 : resources.Count;
            if (n == 0) return;
            ManifestResourceRow[] mresources = this.writer.manifestResourceTable = new ManifestResourceRow[n];
            for (int i = 0; i < n; i++)
            {
                Resource r = resources[i];
                mresources[i].Flags = r.IsPublic ? 1 : 2;
                mresources[i].Name = this.GetStringIndex(r.Name);
                if (r.Data != null)
                    mresources[i].Offset = this.GetResourceDataIndex(r.Data);
                else if (r.DefiningModule is AssemblyNode)
                    mresources[i].Implementation = (this.GetAssemblyRefIndex((AssemblyNode)r.DefiningModule) << 2) | 1;
                else
                    mresources[i].Implementation = (this.GetFileTableIndex(r.DefiningModule) << 2) | 0;
            }
        }
        void PopulateMarshalTable()
        {
            int n = this.marshalEntries.Count;
            if (n == 0) return;
            FieldMarshalRow[] fmr = this.writer.fieldMarshalTable = new FieldMarshalRow[n];
            for (int i = 0; i < n; i++)
            {
                MarshallingInformation mi;
                Field f = this.marshalEntries[i] as Field;
                if (f != null)
                {
                    fmr[i].Parent = (this.GetFieldIndex(f) << 1) | 0;
                    mi = f.MarshallingInformation;
                }
                else
                {
                    Parameter p = (Parameter)this.marshalEntries[i];
                    fmr[i].Parent = (this.GetParamIndex(p) << 1) | 1;
                    mi = p.MarshallingInformation;
                }
                int nt = fmr[i].NativeType = this.GetBlobIndex(mi);
                int pi = fmr[i].Parent;
                for (int k = 0; k < i; k++)
                { //REVIEW: is a more efficient sort worthwhile?
                    if (fmr[k].Parent > pi)
                    {
                        for (int kk = i; kk > k; kk--)
                        {
                            fmr[kk].Parent = fmr[kk - 1].Parent;
                            fmr[kk].NativeType = fmr[kk - 1].NativeType;
                        }
                        fmr[k].Parent = pi;
                        fmr[k].NativeType = nt;
                        break;
                    }
                }
            }
            //this.marshalEntries = null;
        }
        void PopulateMemberRefTable()
        {
            int n = this.memberRefEntries.Count;
            if (n == 0) return;
            MemberRefRow[] mr = this.writer.memberRefTable = new MemberRefRow[n];
            for (int i = 0; i < n; i++)
            {
                Member member = this.memberRefEntries[i];
                if (member == null || member.Name == null) continue;
                mr[i].Name = this.GetStringIndex(member.Name.ToString());
                Field f = member as Field;
                if (f != null)
                    mr[i].Signature = this.GetBlobIndex(f);
                else
                {
                    FunctionPointer fp = member as FunctionPointer;
                    if (fp != null)
                    {
                        mr[i].Signature = this.GetBlobIndex(fp);
                        if (fp is VarargMethodCallSignature)
                        {
                            Method m = ((VarargMethodCallSignature)member).method;
                            if (m != null && m.DeclaringType.DeclaringModule == this.module && !this.IsStructural(m.DeclaringType))
                            {
                                mr[i].Class = (this.GetMethodIndex(m) << 3) | 3;
                                continue;
                            }
                        }
                    }
                    else
                    {
                        Method m = (Method)member;
                        if (m.IsGeneric && m.Template != null) m = this.GetUnspecializedMethod(m);
                        mr[i].Signature = this.GetBlobIndex(m, false);
                        if (m.DeclaringType.DeclaringModule == this.module && !this.IsStructural(m.DeclaringType) && !m.IsGeneric)
                        {
                            mr[i].Class = (this.GetMethodIndex(m) << 3) | 3;
                            continue;
                        }
                        //TODO: if the declaring type is the special global members type of another module, set class to a module ref
                    }
                }
                int j = mr[i].Class = this.GetMemberRefParentEncoded(member.DeclaringType);
                if ((j & 0x3) == 2) mr[i].Class = (j & ~0x3) | 4;
            }
            //this.memberRefEntries = null;
        }
        void PopulateMethodTable()
        {
            int n = this.methodEntries.Count;
            if (n == 0) return;
            MethodRow[] mr = this.writer.methodTable = new MethodRow[n];
            for (int i = 0; i < n; i++)
            {
                Method m = this.methodEntries[i];
                if (m == null || m.Name == null) continue;
                if (m.IsAbstract || m.Body == null || m.Body.Statements == null || m.Body.Statements.Count == 0)
                    mr[i].RVA = -1;
                else
                    mr[i].RVA = this.GetMethodBodiesHeapIndex(m); //Fixed up to be an RVA inside MetadataWriter.
                mr[i].Flags = (int)m.Flags;
                mr[i].ImplFlags = (int)m.ImplFlags;
                mr[i].Name = this.GetStringIndex(m.Name.ToString());
                mr[i].Signature = this.GetBlobIndex(m, false);
                if (m.ReturnTypeMarshallingInformation != null || (m.ReturnAttributes != null && m.ReturnAttributes.Count > 0))
                    mr[i].ParamList = (int)this.paramIndex[m.UniqueKey];
                else
                {
                    ParameterList pars = m.Parameters;
                    if (pars != null && pars.Count > 0)
                    {
                        Debug.Assert(pars[0] != null && pars[0].DeclaringMethod == m);
                        mr[i].ParamList = this.GetParamIndex(pars[0]);
                    }
                    else
                        mr[i].ParamList = 0;
                }
            }
            //this.methodEntries = null;
        }
        void PopulateMethodImplTable()
        {
            int n = this.methodImplEntries.Count;
            if (n == 0) return;
            MethodImplRow[] mir = this.writer.methodImplTable = new MethodImplRow[n];
            int j = 0;
            Method lastMethod = null;
            for (int i = 0; i < n; i++)
            {
                Method m = this.methodImplEntries[i];
                if (lastMethod != m) j = 0;
                mir[i].Class = this.GetTypeDefIndex(m.DeclaringType);
                if (m.DeclaringType.DeclaringModule == this.module)
                    mir[i].MethodBody = this.GetMethodIndex(m) << 1;
                else
                    mir[i].MethodBody = (this.GetMemberRefIndex(m) << 1) | 0x1;
                Method im = m.ImplementedInterfaceMethods[j++];
                while (im == null) im = m.ImplementedInterfaceMethods[j++];
                mir[i].MethodDeclaration = this.GetMethodDefOrRefEncoded(im);
                lastMethod = m;
            }
            //this.methodImplEntries = null;
        }
        void PopulateMethodSpecTable()
        {
            int n = this.methodSpecEntries.Count;
            if (n == 0) return;
            MethodSpecRow[] msr = this.writer.methodSpecTable = new MethodSpecRow[n];
            for (int i = 0; i < n; i++)
            {
                Method m = this.methodSpecEntries[i];
                msr[i].Method = this.GetMethodDefOrRefEncoded(m.Template);
                msr[i].Instantiation = this.GetBlobIndex(m, true);
                //TODO: sort this and eliminate duplicates.
                //Duplicates can arise when methods are instantiated with method parameters from different methods.
                //TODO: perhaps this duplication should be prevented by Method.GetTemplateInstance?
            }
            //this.methodEntries = null;
        }
        void PopulateMethodSemanticsTable()
        {
            int n = this.methodSemanticsEntries.Count;
            if (n == 0) return;
            MethodSemanticsRow[] msr = this.writer.methodSemanticsTable = new MethodSemanticsRow[n];
            Member previousOwner = null;
            int index = -1;
            for (int i = 0; i < n; i++)
            {
                Member owner = this.methodSemanticsEntries[i];
                Property ownerProperty = owner as Property;
                if (ownerProperty != null)
                {
                    msr[i].Association = (this.GetPropertyIndex(ownerProperty) << 1) | 1;
                    if (owner != previousOwner)
                    {
                        previousOwner = owner;
                        index = -1;
                        if (ownerProperty.Getter != null)
                        {
                            msr[i].Method = this.GetMethodIndex(ownerProperty.Getter);
                            msr[i].Semantics = 0x0002;
                            continue;
                        }
                    }
                    if (index == -1)
                    {
                        index = 0;
                        if (ownerProperty.Setter != null)
                        {
                            msr[i].Method = this.GetMethodIndex(ownerProperty.Setter);
                            msr[i].Semantics = 0x0001;
                            continue;
                        }
                    }
                    msr[i].Method = this.GetMethodIndex(ownerProperty.OtherMethods[index]);
                    msr[i].Semantics = 0x0004;
                    index++;
                    continue;
                }
                Event ownerEvent = owner as Event;
                if (ownerEvent == null) { Debug.Fail(""); continue; }
                msr[i].Association = this.GetEventIndex(ownerEvent) << 1;
                if (owner != previousOwner)
                {
                    previousOwner = owner;
                    index = -2;
                    if (ownerEvent.HandlerAdder != null)
                    {
                        msr[i].Method = this.GetMethodIndex(ownerEvent.HandlerAdder);
                        msr[i].Semantics = 0x0008;
                        continue;
                    }
                }
                if (index == -2)
                {
                    index = -1;
                    if (ownerEvent.HandlerRemover != null)
                    {
                        msr[i].Method = this.GetMethodIndex(ownerEvent.HandlerRemover);
                        msr[i].Semantics = 0x0010;
                        continue;
                    }
                }
                if (index == -1)
                {
                    index = 0;
                    if (ownerEvent.HandlerCaller != null)
                    {
                        msr[i].Method = this.GetMethodIndex(ownerEvent.HandlerCaller);
                        msr[i].Semantics = 0x0020;
                        continue;
                    }
                }
                msr[i].Method = this.GetMethodIndex(ownerEvent.OtherMethods[i]);
                msr[i].Semantics = 0x0004;
                index++;
                continue;
            }
            System.Array.Sort(msr, new MethodSemanticsRowComparer());
            //this.methodSemanticsEntries = null;
        }
        class MethodSemanticsRowComparer : IComparer
        {
            int IComparer.Compare(object x, object y)
            {
                MethodSemanticsRow xr = (MethodSemanticsRow)x;
                MethodSemanticsRow yr = (MethodSemanticsRow)y;
                int result = xr.Association - yr.Association;
                if (result == 0) result = xr.Method - yr.Method;
                return result;
            }
        }
        void PopulateModuleTable()
        {
            ModuleRow[] mr = this.writer.moduleTable = new ModuleRow[1];
            string name = this.module.Name;
            if (this.assembly != null)
            {
                if (this.assembly.ModuleName != null)
                    name = this.assembly.ModuleName;
                else
                {
                    string extension = ".exe";
                    if (this.module.Kind == ModuleKindFlags.DynamicallyLinkedLibrary) extension = ".dll";
                    name = name + extension;
                }
            }
            mr[0].Name = this.GetStringIndex(name);
            mr[0].Mvid = this.GetGuidIndex(Guid.NewGuid());
        }
        void PopulateModuleRefTable()
        {
            int n = this.moduleRefEntries.Count;
            if (n == 0) return;
            ModuleRefRow[] mrr = this.writer.moduleRefTable = new ModuleRefRow[n];
            for (int i = 0; i < n; i++)
            {
                ModuleReference moduleRef = this.moduleRefEntries[i];
                mrr[i].Name = this.GetStringIndex(moduleRef.Name);
            }
            //this.moduleRefEntries = null;
        }
        void PopulateNestedClassTable()
        {
            int n = this.nestedClassEntries.Count;
            if (n == 0) return;
            NestedClassRow[] ncr = this.writer.nestedClassTable = new NestedClassRow[n];
            for (int i = 0; i < n; i++)
            {
                TypeNode nt = this.nestedClassEntries[i];
                ncr[i].NestedClass = this.GetTypeDefIndex(nt);
                ncr[i].EnclosingClass = this.GetTypeDefIndex(nt.DeclaringType);
            }
            //this.nestedClassEntries = null;
        }
        void PopulateParamTable()
        {
            int n = this.paramEntries.Count;
            if (n == 0) return;
            ParamRow[] pr = this.writer.paramTable = new ParamRow[n];
            for (int i = 0; i < n; i++)
            {
                Parameter p = this.paramEntries[i];
                if (p == null) continue;
                pr[i].Flags = (int)p.Flags;
                pr[i].Sequence = p.ParameterListIndex + 1;
                pr[i].Name = p.Name == null ? 0 : this.GetStringIndex(p.Name.ToString());
            }
            //this.paramEntries = null;
        }
        void PopulatePropertyTable()
        {
            int n = this.propertyEntries.Count;
            if (n == 0) return;
            PropertyRow[] pr = this.writer.propertyTable = new PropertyRow[n];
            for (int i = 0; i < n; i++)
            {
                Property p = this.propertyEntries[i];
                if (p == null || p.Name == null) continue;
                pr[i].Flags = (int)p.Flags;
                pr[i].Name = this.GetStringIndex(p.Name.ToString());
                pr[i].Signature = this.GetBlobIndex(p);
            }
            //this.propertyEntries = null;
        }
        void PopulatePropertyMapTable()
        {
            int n = this.propertyMapEntries.Count;
            if (n == 0) return;
            PropertyMapRow[] pmr = this.writer.propertyMapTable = new PropertyMapRow[n];
            for (int i = 0; i < n; i++)
            {
                Property p = this.propertyMapEntries[i];
                pmr[i].Parent = this.GetTypeDefIndex(p.DeclaringType);
                pmr[i].PropertyList = this.GetPropertyIndex(p);
            }
            //this.propertyMapEntries = null;
        }
        void PopulateStandAloneSigTable()
        {
            int n = this.standAloneSignatureEntries.Count;
            if (n == 0) return;
            StandAloneSigRow[] sasr = this.writer.standAloneSigTable = new StandAloneSigRow[n];
            for (int i = 0; i < n; i++)
            {
                BinaryWriter sigWriter = (BinaryWriter)this.standAloneSignatureEntries[i];
                sasr[i].Signature = this.GetBlobIndex(((MemoryStream)sigWriter.BaseStream).ToArray());
            }
        }
        void PopulateTypeDefTable()
        {
            int n = this.typeDefEntries.Count;
            if (n == 0) return;
            TypeDefRow[] tdr = this.writer.typeDefTable = new TypeDefRow[n];
            for (int i = 0; i < n; i++)
            {
                TypeNode t = this.typeDefEntries[i];
                if (t == null) continue;
                tdr[i].Flags = (int)t.Flags;
                tdr[i].Name = this.GetStringIndex(t.Name == null ? "" : t.Name.ToString());
                tdr[i].Namespace = t.Namespace == null ? 0 : this.GetStringIndex(t.Namespace == null ? "" : t.Namespace.ToString());
                tdr[i].Extends = this.GetTypeDefOrRefOrSpecEncoded(t.BaseType);
                MemberList members = t.Members;
                int m = members.Count;
                for (int j = 0; j < m; j++)
                {
                    Member mem = members[j];
                    if (mem == null) continue;
                    if (mem.NodeType == NodeType.Field)
                    {
                        tdr[i].FieldList = this.GetFieldIndex((Field)mem);
                        break;
                    }
                }
                for (int j = 0; j < m; j++)
                {
                    Member mem = members[j];
                    if (mem == null) continue;
                    switch (mem.NodeType)
                    {
                        case NodeType.Method:
                        case NodeType.InstanceInitializer:
                        case NodeType.StaticInitializer:
                            tdr[i].MethodList = this.GetMethodIndex((Method)mem);
                            goto done;
                    }
                }
            done: continue;
            }
            //this.typeDefEntries = null;
        }
        void PopulateTypeRefTable()
        {
            int n = this.typeRefEntries.Count;
            if (n == 0) return;
            TypeRefRow[] trr = this.writer.typeRefTable = new TypeRefRow[n];
            for (int i = 0; i < n; i++)
            {
                TypeNode t = this.typeRefEntries[i];
                if (t == null || t.Name == null || t.Namespace == null) continue;
                trr[i].Name = this.GetStringIndex(t.Name.ToString());
                trr[i].Namespace = this.GetStringIndex(t.Namespace.ToString());
                if (t.DeclaringType == null)
                    if (t.DeclaringModule is AssemblyNode)
                        trr[i].ResolutionScope = (this.GetAssemblyRefIndex((AssemblyNode)t.DeclaringModule) << 2) | 2;
                    else
                        trr[i].ResolutionScope = (this.GetModuleRefIndex(t.DeclaringModule) << 2) | 1;
                else
                    trr[i].ResolutionScope = (this.GetTypeRefIndex(t.DeclaringType) << 2) | 3;
            }
            //this.typeRefEntries = null;
        }
        void PopulateTypeSpecTable()
        {
            int n = this.typeSpecEntries.Count;
            if (n == 0) return;
            TypeSpecRow[] tsr = this.writer.typeSpecTable = new TypeSpecRow[n];
            for (int i = 0; i < n; i++)
            {
                TypeNode t = this.typeSpecEntries[i];
                tsr[i].Signature = this.GetBlobIndex(t);
                //TODO: eliminate duplicates
            }
            //this.typeSpecEntries = null;
        }
        void Visit(Node node)
        {
            if (node == null) return;
            switch (node.NodeType)
            {
                case NodeType.AddressDereference:
                    this.VisitAddressDereference((AddressDereference)node); return;
                case NodeType.Arglist:
                    this.VisitExpression((Expression)node); return;
                case NodeType.AssignmentStatement:
                    this.VisitAssignmentStatement((AssignmentStatement)node); return;
#if !MinimalReader
                case NodeType.Base:
                    this.VisitBase((Base)node); return;
#endif
                case NodeType.Block:
                    this.VisitBlock((Block)node); return;
#if !MinimalReader
                case NodeType.BlockExpression:
                    this.VisitBlockExpression((BlockExpression)node); return;
#endif
                case NodeType.Branch:
                    this.VisitBranch((Branch)node); return;
                case NodeType.DebugBreak:
                    this.VisitStatement((Statement)node); return;
                case NodeType.Call:
                case NodeType.Calli:
                case NodeType.Callvirt:
                case NodeType.Jmp:
#if !MinimalReader
                case NodeType.MethodCall:
#endif
                    this.VisitMethodCall((MethodCall)node); return;
                case NodeType.Class:
                case NodeType.ClassParameter:
                    this.VisitClass((Class)node); return;
                case NodeType.Construct:
                    this.VisitConstruct((Construct)node); return;
                case NodeType.ConstructArray:
                    this.VisitConstructArray((ConstructArray)node); return;
                case NodeType.DelegateNode:
                    this.VisitDelegateNode((DelegateNode)node); return;
                case NodeType.Dup:
                    this.VisitExpression((Expression)node); return;
                case NodeType.EndFilter:
                    this.VisitEndFilter((EndFilter)node); return;
                case NodeType.EndFinally:
                    this.VisitStatement((Statement)node); return;
                case NodeType.EnumNode:
                    this.VisitEnumNode((EnumNode)node); return;
                case NodeType.Event:
                    this.VisitEvent((Event)node); return;
                case NodeType.ExpressionStatement:
                    this.VisitExpressionStatement((ExpressionStatement)node); return;
                case NodeType.Field:
                    this.VisitField((Field)node); return;
                case NodeType.Indexer:
                    this.VisitIndexer((Indexer)node); return;
                case NodeType.InstanceInitializer:
                case NodeType.StaticInitializer:
                case NodeType.Method:
                    this.VisitMethod((Method)node); return;
                case NodeType.TypeParameter:
                case NodeType.Interface:
                    this.VisitInterface((Interface)node); return;
                case NodeType.Literal:
                    this.VisitLiteral((Literal)node); return;
                case NodeType.Local:
                    this.VisitLocal((Local)node); return;
#if !MinimalReader
                case NodeType.LocalDeclarationsStatement:
                    this.VisitLocalDeclarationsStatement((LocalDeclarationsStatement)node); return;
#endif
                case NodeType.MemberBinding:
                    this.VisitMemberBinding((MemberBinding)node); return;
                case NodeType.Nop:
                    this.VisitStatement((Statement)node); return;
                case NodeType.Parameter:
                    this.VisitParameter((Parameter)node); return;
                case NodeType.Pop:
                    this.VisitExpression((Expression)node); return;
                case NodeType.Property:
                    this.VisitProperty((Property)node); return;
                case NodeType.Rethrow:
                case NodeType.Throw:
                    this.VisitThrow((Throw)node); return;
                case NodeType.Return:
                    this.VisitReturn((Return)node); return;
                case NodeType.Struct:
#if !MinimalReader
                case NodeType.TypeAlias:
                case NodeType.TypeIntersection:
                case NodeType.TypeUnion:
                case NodeType.TupleType:
#endif
                    this.VisitStruct((Struct)node); return;
#if !MinimalReader
                case NodeType.SwitchCaseBottom:
                    return;
#endif
                case NodeType.SwitchInstruction:
                    this.VisitSwitchInstruction((SwitchInstruction)node); return;
                case NodeType.This:
                    this.VisitThis((This)node); return;

                case NodeType.Cpblk:
                case NodeType.Initblk:
                    this.VisitTernaryExpression((TernaryExpression)node); return;

                case NodeType.Add:
                case NodeType.Add_Ovf:
                case NodeType.Add_Ovf_Un:
                case NodeType.And:
                case NodeType.Box:
                case NodeType.Castclass:
                case NodeType.Ceq:
                case NodeType.Cgt:
                case NodeType.Cgt_Un:
                case NodeType.Clt:
                case NodeType.Clt_Un:
                case NodeType.Div:
                case NodeType.Div_Un:
                case NodeType.Eq:
                case NodeType.Ge:
                case NodeType.Gt:
#if !MinimalReader
                case NodeType.Is:
#endif
                case NodeType.Isinst:
                case NodeType.Ldvirtftn:
                case NodeType.Le:
                case NodeType.Lt:
                case NodeType.Mkrefany:
                case NodeType.Mul:
                case NodeType.Mul_Ovf:
                case NodeType.Mul_Ovf_Un:
                case NodeType.Ne:
                case NodeType.Or:
                case NodeType.Refanyval:
                case NodeType.Rem:
                case NodeType.Rem_Un:
                case NodeType.Shl:
                case NodeType.Shr:
                case NodeType.Shr_Un:
                case NodeType.Sub:
                case NodeType.Sub_Ovf:
                case NodeType.Sub_Ovf_Un:
                case NodeType.Unbox:
                case NodeType.UnboxAny:
                case NodeType.Xor:
                    this.VisitBinaryExpression((BinaryExpression)node); return;


                case NodeType.AddressOf:
#if !MinimalReader
                case NodeType.OutAddress:
                case NodeType.RefAddress:
#endif
                case NodeType.ReadOnlyAddressOf:
                    this.VisitAddressOf((UnaryExpression)node); return;
                case NodeType.Ckfinite:
                case NodeType.Conv_I:
                case NodeType.Conv_I1:
                case NodeType.Conv_I2:
                case NodeType.Conv_I4:
                case NodeType.Conv_I8:
                case NodeType.Conv_Ovf_I:
                case NodeType.Conv_Ovf_I1:
                case NodeType.Conv_Ovf_I1_Un:
                case NodeType.Conv_Ovf_I2:
                case NodeType.Conv_Ovf_I2_Un:
                case NodeType.Conv_Ovf_I4:
                case NodeType.Conv_Ovf_I4_Un:
                case NodeType.Conv_Ovf_I8:
                case NodeType.Conv_Ovf_I8_Un:
                case NodeType.Conv_Ovf_I_Un:
                case NodeType.Conv_Ovf_U:
                case NodeType.Conv_Ovf_U1:
                case NodeType.Conv_Ovf_U1_Un:
                case NodeType.Conv_Ovf_U2:
                case NodeType.Conv_Ovf_U2_Un:
                case NodeType.Conv_Ovf_U4:
                case NodeType.Conv_Ovf_U4_Un:
                case NodeType.Conv_Ovf_U8:
                case NodeType.Conv_Ovf_U8_Un:
                case NodeType.Conv_Ovf_U_Un:
                case NodeType.Conv_R4:
                case NodeType.Conv_R8:
                case NodeType.Conv_R_Un:
                case NodeType.Conv_U:
                case NodeType.Conv_U1:
                case NodeType.Conv_U2:
                case NodeType.Conv_U4:
                case NodeType.Conv_U8:
                case NodeType.Ldftn:
                case NodeType.Ldlen:
                case NodeType.Ldtoken:
                case NodeType.Localloc:
                case NodeType.Neg:
                case NodeType.Not:
                case NodeType.Refanytype:
                case NodeType.Sizeof:
                    this.VisitUnaryExpression((UnaryExpression)node); return;

                default:
                    // handle type extensions with new NodeType's, that are emitted as ordinary structs and classes
                    Class cl = node as Class;
                    if (cl != null)
                    {
                        this.VisitClass(cl); return;
                    }
                    Struct st = node as Struct;
                    if (st != null)
                    {
                        this.VisitStruct(st); return;
                    }
                    Debug.Assert(false, "invalid node: " + node.NodeType.ToString());
                    return;
            }
        }
        void VisitAddressDereference(AddressDereference/*!*/ adr)
        {
            this.Visit(adr.Address);
            if (adr.Alignment > 0)
            {
                this.methodBodyHeap.Write((byte)0xfe);
                this.methodBodyHeap.Write((byte)0x12);
                this.methodBodyHeap.Write((byte)adr.Alignment);
            }
            if (adr.Volatile)
            {
                this.methodBodyHeap.Write((byte)0xfe);
                this.methodBodyHeap.Write((byte)0x13);
            }
            switch (adr.Type.typeCode)
            {
                case ElementType.Int8: this.methodBodyHeap.Write((byte)0x46); return;
                case ElementType.UInt8: this.methodBodyHeap.Write((byte)0x47); return;
                case ElementType.Int16: this.methodBodyHeap.Write((byte)0x48); return;
                case ElementType.Char:
                case ElementType.UInt16: this.methodBodyHeap.Write((byte)0x49); return;
                case ElementType.Int32: this.methodBodyHeap.Write((byte)0x4a); return;
                case ElementType.UInt32: this.methodBodyHeap.Write((byte)0x4b); return;
                case ElementType.Int64:
                case ElementType.UInt64: this.methodBodyHeap.Write((byte)0x4c); return;
                //case ElementType.UIntPtr:
                //case ElementType.IntPtr: this.methodBodyHeap.Write((byte)0x4d); return;
                case ElementType.Single: this.methodBodyHeap.Write((byte)0x4e); return;
                case ElementType.Double: this.methodBodyHeap.Write((byte)0x4f); return;
                default:
                    if (adr.Type.IsValueType || (adr.Type is ITypeParameter && this.UseGenerics))
                    {
                        this.methodBodyHeap.Write((byte)0x71);
                        this.methodBodyHeap.Write((int)this.GetTypeToken(adr.Type));
                        return;
                    }
                    else if (TypeNode.StripModifiers(adr.Type) is Pointer)
                    {
                        this.methodBodyHeap.Write((byte)0x4d); return;
                    }
                    this.methodBodyHeap.Write((byte)0x50);
                    return;
            }
        }
        void VisitAttributeList(AttributeList attrs, Node/*!*/ node)
        {
            if (attrs == null) return;
            int n = attrs.Count;
            if (n == 0) return;
            int m = n;
            for (int j = 0; j < n; j++)
            {
                AttributeNode a = attrs[j];
                if (a == null) m--;
            }
            if (m == 0) return;
            n = m;
            int codedIndex = this.GetCustomAttributeParentCodedIndex(node);
            this.customAttributeCount += n;
            m = this.nodesWithCustomAttributes.Count;
            this.nodesWithCustomAttributes.Add(node);
            int i = 0; //after the for loop i will be position where the new node should be in sorted list
            NodeList nodes = this.nodesWithCustomAttributes;
            for (i = m; i > 0; i--)
            {
                Node other = nodes[i - 1];
                int oci = this.GetCustomAttributeParentCodedIndex(other);
                if (oci < codedIndex) break;
                if (UseGenerics)
                {
                    if (oci == codedIndex) Debug.Assert(false);
                }
            }
            if (i == m) return; //node is already where it should be
            for (int j = m; j > i; j--) nodes[j] = nodes[j - 1]; //Make space at postion i
            nodes[i] = node;
        }
        void VisitAddressOf(UnaryExpression/*!*/ expr)
        {
            Expression operand = expr.Operand;
            if (operand == null) return;
            switch (operand.NodeType)
            {
                case NodeType.Indexer:
                    Indexer indexer = (Indexer)operand;
                    this.Visit(indexer.Object);
                    if (indexer.Operands == null || indexer.Operands.Count < 1) return;
                    this.Visit(indexer.Operands[0]);
                    if (expr.NodeType == NodeType.ReadOnlyAddressOf)
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x1e);
                    }
                    this.methodBodyHeap.Write((byte)0x8f);
                    this.methodBodyHeap.Write((int)this.GetTypeToken(indexer.ElementType));
                    this.stackHeight--;
                    return;
                case NodeType.Local:
                    int li = this.GetLocalVarIndex((Local)operand);
                    if (li < 256)
                    {
                        this.methodBodyHeap.Write((byte)0x12);
                        this.methodBodyHeap.Write((byte)li);
                    }
                    else
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x0d);
                        this.methodBodyHeap.Write((ushort)li);
                    }
                    this.IncrementStackHeight();
                    return;
                case NodeType.MemberBinding:
                    MemberBinding mb = (MemberBinding)operand;
                    if (mb.TargetObject != null)
                    {
                        this.Visit(mb.TargetObject);
                        this.methodBodyHeap.Write((byte)0x7c);
                    }
                    else
                    {
                        this.methodBodyHeap.Write((byte)0x7f);
                        this.IncrementStackHeight();
                    }
                    this.methodBodyHeap.Write((int)this.GetFieldToken((Field)mb.BoundMember));
                    return;
                case NodeType.Parameter:
#if !MinimalReader
                    ParameterBinding pb = operand as ParameterBinding;
                    if (pb != null) operand = pb.BoundParameter;
#endif
                    int pi = ((Parameter)operand).ArgumentListIndex;
                    if (pi < 256)
                    {
                        this.methodBodyHeap.Write((byte)0x0f);
                        this.methodBodyHeap.Write((byte)pi);
                    }
                    else
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x0a);
                        this.methodBodyHeap.Write((ushort)pi);
                    }
                    this.IncrementStackHeight();
                    return;
            }
        }
        void VisitAssignmentStatement(AssignmentStatement/*!*/ assignment)
        {
            this.DefineSequencePoint(assignment);
            Expression target = assignment.Target;
            switch (assignment.Target.NodeType)
            {
                case NodeType.Local:
                    Local loc = (Local)target;
                    this.Visit(assignment.Source);
                    this.stackHeight--;
                    int li = this.GetLocalVarIndex(loc);
                    switch (li)
                    {
                        case 0: this.methodBodyHeap.Write((byte)0x0a); return;
                        case 1: this.methodBodyHeap.Write((byte)0x0b); return;
                        case 2: this.methodBodyHeap.Write((byte)0x0c); return;
                        case 3: this.methodBodyHeap.Write((byte)0x0d); return;
                        default:
                            if (li < 256)
                            {
                                this.methodBodyHeap.Write((byte)0x13);
                                this.methodBodyHeap.Write((byte)li);
                            }
                            else
                            {
                                this.methodBodyHeap.Write((byte)0xfe);
                                this.methodBodyHeap.Write((byte)0x0e);
                                this.methodBodyHeap.Write((ushort)li);
                            }
                            return;
                    }
                case NodeType.MemberBinding:
                    MemberBinding mb = (MemberBinding)target;
                    if (mb.TargetObject != null) this.Visit(mb.TargetObject);
                    this.Visit(assignment.Source);
                    if (mb.TargetObject != null)
                    {
                        if (mb.Alignment != -1)
                        {
                            this.methodBodyHeap.Write((byte)0xfe);
                            this.methodBodyHeap.Write((byte)0x12);
                            this.methodBodyHeap.Write((byte)mb.Alignment);
                        }
                        if (mb.Volatile)
                        {
                            this.methodBodyHeap.Write((byte)0xfe);
                            this.methodBodyHeap.Write((byte)0x13);
                        }
                        this.methodBodyHeap.Write((byte)0x7d);
                    }
                    else
                    {
                        if (mb.Volatile)
                        {
                            this.methodBodyHeap.Write((byte)0xfe);
                            this.methodBodyHeap.Write((byte)0x13);
                        }
                        this.methodBodyHeap.Write((byte)0x80);
                    }
                    this.methodBodyHeap.Write((int)this.GetFieldToken((Field)mb.BoundMember));
                    if (mb.TargetObject != null)
                        this.stackHeight -= 2;
                    else
                        this.stackHeight--;
                    return;
                case NodeType.Parameter:
#if !MinimalReader
                    ParameterBinding pb = target as ParameterBinding;
                    if (pb != null) target = pb.BoundParameter;
#endif
                    Parameter par = (Parameter)target;
                    this.Visit(assignment.Source);
                    int pi = par.ArgumentListIndex;
                    if (pi < 256)
                    {
                        this.methodBodyHeap.Write((byte)0x10);
                        this.methodBodyHeap.Write((byte)pi);
                    }
                    else
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x0b);
                        this.methodBodyHeap.Write((ushort)pi);
                    }
                    this.stackHeight--;
                    return;
                case NodeType.Indexer:
                    Indexer indexer = (Indexer)target;
                    this.Visit(indexer.Object);
                    if (indexer.Operands == null || indexer.Operands.Count < 1) return;
                    this.Visit(indexer.Operands[0]);
                    this.Visit(assignment.Source);
                    byte opCode;
                    switch (indexer.ElementType.typeCode)
                    {
                        case ElementType.UIntPtr:
                        case ElementType.IntPtr: opCode = 0x9b; break;
                        case ElementType.Boolean:
                        case ElementType.Int8:
                        case ElementType.UInt8: opCode = 0x9c; break;
                        case ElementType.Char:
                        case ElementType.Int16:
                        case ElementType.UInt16: opCode = 0x9d; break;
                        case ElementType.Int32:
                        case ElementType.UInt32: opCode = 0x9e; break;
                        case ElementType.Int64:
                        case ElementType.UInt64: opCode = 0x9f; break;
                        case ElementType.Single: opCode = 0xa0; break;
                        case ElementType.Double: opCode = 0xa1; break;
                        default:
                            if (this.UseGenerics && (indexer.ElementType is ITypeParameter))
                                opCode = 0xa4;
                            else if (TypeNode.StripModifiers(indexer.ElementType) is Pointer)
                                opCode = 0x9b;
                            else
                                opCode = 0xa2;
                            break;
                    }
                    this.methodBodyHeap.Write((byte)opCode);
                    if (opCode == 0xa4) this.methodBodyHeap.Write((int)this.GetTypeToken(indexer.ElementType));
                    this.stackHeight -= 3;
                    return;
                case NodeType.AddressDereference:
                    AddressDereference adr = (AddressDereference)target;
                    this.Visit(adr.Address);
                    if (adr.Type.IsValueType || adr.Type is ITypeParameter)
                    {
                        Literal lit = assignment.Source as Literal;
                        if (lit != null && lit.Value == null)
                        {
                            this.methodBodyHeap.Write((byte)0xfe);
                            this.methodBodyHeap.Write((byte)0x15);
                            this.methodBodyHeap.Write((int)this.GetTypeToken(adr.Type));
                            this.stackHeight--;
                            return;
                        }
                    }
                    this.Visit(assignment.Source);
                    this.stackHeight -= 2;
                    if (adr.Alignment > 0)
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x12);
                        this.methodBodyHeap.Write((byte)adr.Alignment);
                    }
                    if (adr.Volatile)
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x13);
                    }
                    TypeNode adrType = TypeNode.StripModifiers(adr.Type);
                    if (adrType == null) return;
                    switch (adrType.typeCode)
                    {
                        case ElementType.Int8:
                        case ElementType.UInt8: this.methodBodyHeap.Write((byte)0x52); return;
                        case ElementType.Int16:
                        case ElementType.UInt16: this.methodBodyHeap.Write((byte)0x53); return;
                        case ElementType.Int32:
                        case ElementType.UInt32: this.methodBodyHeap.Write((byte)0x54); return;
                        case ElementType.Int64:
                        case ElementType.UInt64: this.methodBodyHeap.Write((byte)0x55); return;
                        case ElementType.Single: this.methodBodyHeap.Write((byte)0x56); return;
                        case ElementType.Double: this.methodBodyHeap.Write((byte)0x57); return;
                        case ElementType.UIntPtr:
                        case ElementType.IntPtr: this.methodBodyHeap.Write((byte)0xdf); return;
                        default:
                            if (adrType != null && (adrType.IsValueType ||
                              this.UseGenerics && (adrType is ITypeParameter)))
                            {
                                this.methodBodyHeap.Write((byte)0x81);
                                this.methodBodyHeap.Write((int)this.GetTypeToken(adrType));
                                return;
                            }
                            if (adrType.NodeType == NodeType.Pointer)
                            {
                                this.methodBodyHeap.Write((byte)0xdf); return;
                            }
                            this.methodBodyHeap.Write((byte)0x51);
                            return;
                    }
                default:
                    Debug.Assert(false, "unexpected assignment target");
                    return;
            }
        }
#if !MinimalReader
        void VisitBase(Base/*!*/ Base)
        {
            this.IncrementStackHeight();
            this.methodBodyHeap.Write((byte)0x02);
        }
#endif
        void VisitBinaryExpression(BinaryExpression/*!*/ binaryExpression)
        {
            byte opCode = 0;
            this.Visit(binaryExpression.Operand1);
            switch (binaryExpression.NodeType)
            {
                case NodeType.Castclass: opCode = 0x74; goto writeOpCodeAndToken;
                case NodeType.Isinst: opCode = 0x75; goto writeOpCodeAndToken;
                case NodeType.Unbox: opCode = 0x79; goto writeOpCodeAndToken;
                case NodeType.UnboxAny: opCode = 0xa5; goto writeOpCodeAndToken;
                case NodeType.Box: opCode = 0x8c; goto writeOpCodeAndToken;
                case NodeType.Refanyval: opCode = 0xc2; goto writeOpCodeAndToken;
                case NodeType.Mkrefany: opCode = 0xc6; goto writeOpCodeAndToken;
                writeOpCodeAndToken:
                    this.methodBodyHeap.Write((byte)opCode);
                Literal lit = binaryExpression.Operand2 as Literal;
                if (lit != null)
                    this.methodBodyHeap.Write((int)this.GetTypeToken((TypeNode)lit.Value));
                else
                {
                    // TODO: Normalized IR should never use a MemberBinding to represent a type
                    this.methodBodyHeap.Write((int)this.GetTypeToken((TypeNode)((MemberBinding)binaryExpression.Operand2).BoundMember));
                }
                return;
                case NodeType.Ldvirtftn: opCode = 0x07; this.methodBodyHeap.Write((byte)0xfe);
                this.methodBodyHeap.Write((byte)opCode);
                this.methodBodyHeap.Write((int)this.GetMethodToken((Method)((MemberBinding)binaryExpression.Operand2).BoundMember));
                return;
            }
            this.Visit(binaryExpression.Operand2);
            switch (binaryExpression.NodeType)
            {
                case NodeType.Add: opCode = 0x58; break;
                case NodeType.Sub: opCode = 0x59; break;
                case NodeType.Mul: opCode = 0x5a; break;
                case NodeType.Div: opCode = 0x5b; break;
                case NodeType.Div_Un: opCode = 0x5c; break;
                case NodeType.Rem: opCode = 0x5d; break;
                case NodeType.Rem_Un: opCode = 0x5e; break;
                case NodeType.And: opCode = 0x5f; break;
                case NodeType.Or: opCode = 0x60; break;
                case NodeType.Xor: opCode = 0x61; break;
                case NodeType.Shl: opCode = 0x62; break;
                case NodeType.Shr: opCode = 0x63; break;
                case NodeType.Shr_Un: opCode = 0x64; break;
                case NodeType.Add_Ovf: opCode = 0xd6; break;
                case NodeType.Add_Ovf_Un: opCode = 0xd7; break;
                case NodeType.Mul_Ovf: opCode = 0xd8; break;
                case NodeType.Mul_Ovf_Un: opCode = 0xd9; break;
                case NodeType.Sub_Ovf: opCode = 0xda; break;
                case NodeType.Sub_Ovf_Un: opCode = 0xdb; break;
                case NodeType.Ceq: opCode = 0x01; this.methodBodyHeap.Write((byte)0xfe); break;
                case NodeType.Cgt: opCode = 0x02; this.methodBodyHeap.Write((byte)0xfe); break;
                case NodeType.Cgt_Un: opCode = 0x03; this.methodBodyHeap.Write((byte)0xfe); break;
                case NodeType.Clt: opCode = 0x04; this.methodBodyHeap.Write((byte)0xfe); break;
                case NodeType.Clt_Un: opCode = 0x05; this.methodBodyHeap.Write((byte)0xfe); break;
            }
            this.methodBodyHeap.Write((byte)opCode);
            this.stackHeight--;
        }
        void VisitBlock(Block/*!*/ block)
        {
            MethodInfo mInfo = this.methodInfo;
            int currentAddress = (int)this.methodBodyHeap.BaseStream.Position;
            this.VisitFixupList((Fixup)this.methodInfo.fixupIndex[block.UniqueKey], currentAddress);
            mInfo.fixupIndex[block.UniqueKey] = currentAddress;
            this.methodBodyHeap.BaseStream.Position = currentAddress;
            int savedStackHeight = this.stackHeight;
            if (this.exceptionBlock[block.UniqueKey] != null) this.stackHeight = 1;
            StatementList statements = block.Statements;
            if (statements == null) return;
#if !ROTOR
            if (this.symWriter != null && block.HasLocals)
            {
                LocalList savedDebugLocals = mInfo.debugLocals;
                Int32List savedSignatureLengths = mInfo.signatureLengths;
                Int32List savedSignatureOffsets = mInfo.signatureOffsets;
                mInfo.debugLocals = new LocalList();
                mInfo.signatureLengths = new Int32List();
                mInfo.signatureOffsets = new Int32List();
                this.symWriter.OpenScope((uint)currentAddress);
                for (int i = 0, n = statements.Count; i < n; i++)
                    this.Visit(statements[i]);
                if (this.stackHeight > 0) this.stackHeightExitTotal += this.stackHeight;
                this.DefineLocalVariables(currentAddress, mInfo.debugLocals);
                mInfo.debugLocals = savedDebugLocals;
                mInfo.signatureLengths = savedSignatureLengths;
                mInfo.signatureOffsets = savedSignatureOffsets;
            }
            else
            {
#endif
                for (int i = 0, n = statements.Count; i < n; i++)
                    this.Visit(statements[i]);
                if (this.stackHeight > savedStackHeight) this.stackHeightExitTotal += (this.stackHeight - savedStackHeight);
#if !ROTOR
            }
#endif
            this.stackHeight = savedStackHeight;
        }
#if !MinimalReader
        void VisitBlockExpression(BlockExpression/*!*/ blockExpression)
        {
            if (blockExpression.Block == null) return;
            this.VisitBlock(blockExpression.Block);
        }
#endif
        void VisitBranch(Branch/*!*/ branch)
        {
            this.DefineSequencePoint(branch);
            BinaryExpression bex = branch.Condition as BinaryExpression;
            UnaryExpression uex = null;
            NodeType typeOfCondition = NodeType.Nop;
            if (bex != null)
            {
                switch (bex.NodeType)
                {
                    case NodeType.Eq:
                    case NodeType.Ge:
                    case NodeType.Gt:
                    case NodeType.Le:
                    case NodeType.Lt:
                    case NodeType.Ne:
                        this.Visit(bex.Operand1);
                        this.Visit(bex.Operand2);
                        typeOfCondition = bex.NodeType;
                        this.stackHeight -= 2;
                        break;
                    case NodeType.And:
                    case NodeType.Or:
                    case NodeType.Xor:
                    case NodeType.Isinst:
                    case NodeType.Castclass:
                        typeOfCondition = bex.NodeType;
                        goto default;
                    default:
                        this.Visit(branch.Condition);
                        this.stackHeight--;
                        break;
                }
            }
            else
            {
                uex = branch.Condition as UnaryExpression;
                if (uex != null && uex.NodeType == NodeType.LogicalNot)
                {
                    this.Visit(uex.Operand);
                    typeOfCondition = NodeType.LogicalNot;
                    this.stackHeight--;
                }
                else if (branch.Condition != null)
                {
                    // Undefined is used here simply as a sentinel value
                    typeOfCondition = NodeType.Undefined;
                    this.Visit(branch.Condition);
                    this.stackHeight--;
                }
            }
            int target = this.GetOffset(branch.Target, ref branch.shortOffset);
            if (branch.ShortOffset)
            {
                switch (typeOfCondition)
                {
                    case NodeType.Nop:
                        if (branch.Condition == null)
                        {
                            if (branch.LeavesExceptionBlock)
                                this.methodBodyHeap.Write((byte)0xde);
                            else
                                this.methodBodyHeap.Write((byte)0x2b);
                            break;
                        }
                        else
                        {
                            this.methodBodyHeap.Write((byte)0x2d); break;
                        }
                    case NodeType.And:
                    case NodeType.Or:
                    case NodeType.Xor:
                    case NodeType.Isinst:
                    case NodeType.Castclass:
                    case NodeType.Undefined:
                        this.methodBodyHeap.Write((byte)0x2d); break;
                    case NodeType.LogicalNot:
                        this.methodBodyHeap.Write((byte)0x2c); break;
                    case NodeType.Eq:
                        this.methodBodyHeap.Write((byte)0x2e); break;
                    case NodeType.Ge:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x34);
                        else
                            this.methodBodyHeap.Write((byte)0x2f);
                        break;
                    case NodeType.Gt:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x35);
                        else
                            this.methodBodyHeap.Write((byte)0x30);
                        break;
                    case NodeType.Le:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x36);
                        else
                            this.methodBodyHeap.Write((byte)0x31);
                        break;
                    case NodeType.Lt:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x37);
                        else
                            this.methodBodyHeap.Write((byte)0x32);
                        break;
                    case NodeType.Ne:
                        this.methodBodyHeap.Write((byte)0x33);
                        break;
                }
                this.methodBodyHeap.Write((sbyte)target);
            }
            else
            {
                switch (typeOfCondition)
                {
                    case NodeType.Nop:
                        if (branch.Condition == null)
                        {
                            if (branch.LeavesExceptionBlock)
                                this.methodBodyHeap.Write((byte)0xdd);
                            else
                                this.methodBodyHeap.Write((byte)0x38);
                            break;
                        }
                        else
                        {
                            this.methodBodyHeap.Write((byte)0x3a); break;
                        }
                    case NodeType.And:
                    case NodeType.Or:
                    case NodeType.Xor:
                    case NodeType.Isinst:
                    case NodeType.Castclass:
                    case NodeType.Undefined:
                        this.methodBodyHeap.Write((byte)0x3a); break;
                    case NodeType.LogicalNot:
                        this.methodBodyHeap.Write((byte)0x39); break;
                    case NodeType.Eq:
                        this.methodBodyHeap.Write((byte)0x3b); break;
                    case NodeType.Ge:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x41);
                        else
                            this.methodBodyHeap.Write((byte)0x3c);
                        break;
                    case NodeType.Gt:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x42);
                        else
                            this.methodBodyHeap.Write((byte)0x3d);
                        break;
                    case NodeType.Le:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x43);
                        else
                            this.methodBodyHeap.Write((byte)0x3e);
                        break;
                    case NodeType.Lt:
                        if (branch.BranchIfUnordered)
                            this.methodBodyHeap.Write((byte)0x44);
                        else
                            this.methodBodyHeap.Write((byte)0x3f);
                        break;
                    case NodeType.Ne:
                        this.methodBodyHeap.Write((byte)0x40); break;
                }
                this.methodBodyHeap.Write((int)target);
            }
        }
        void VisitMethodCall(MethodCall/*!*/ call)
        {
            MemberBinding mb = (MemberBinding)call.Callee;
            TypeNode constraint = call.Constraint;
            this.Visit(mb.TargetObject);
            ExpressionList arguments = call.Operands;
            int pops = 0;
            if (arguments != null)
            {
                this.VisitExpressionList(arguments);
                pops = arguments.Count;
            }
            if (call.Type != CoreSystemTypes.Void) { this.VisitReferencedType(call.Type); pops--; }
            if (pops >= 0)
                this.stackHeight -= pops;
            else
                this.IncrementStackHeight(); //make sure the high water mark moves up if necessary
            if (call.IsTailCall)
            {
                this.methodBodyHeap.Write((byte)0xfe);
                this.methodBodyHeap.Write((byte)0x14);
            }
            else if (constraint != null)
            {
                this.methodBodyHeap.Write((byte)0xfe);
                this.methodBodyHeap.Write((byte)0x16);
                this.methodBodyHeap.Write((int)this.GetTypeToken(constraint));
            }
            switch (call.NodeType)
            {
                case NodeType.Calli:
                    this.methodBodyHeap.Write((byte)0x29);
                    BinaryWriter sig = new BinaryWriter(new MemoryStream());
                    this.WriteMethodSignature(sig, (FunctionPointer)mb.BoundMember);
                    this.methodBodyHeap.Write((int)(0x11000000 | this.GetStandAloneSignatureIndex(sig)));
                    return;
                case NodeType.Callvirt: this.methodBodyHeap.Write((byte)0x6f); break;
                case NodeType.Jmp: this.methodBodyHeap.Write((byte)0x27); break;
                default: this.methodBodyHeap.Write((byte)0x28); break;
            }
            Method method = (Method)mb.BoundMember;
            if ((method.CallingConvention & (CallingConventionFlags)7) == CallingConventionFlags.VarArg ||
              (method.CallingConvention & (CallingConventionFlags)7) == CallingConventionFlags.C)
            {
                this.methodBodyHeap.Write((int)this.GetMemberRefToken(method, arguments));
            }
            else
                this.methodBodyHeap.Write((int)this.GetMethodToken(method));
        }
        void VisitClass(Class/*!*/ Class)
        {
            if (this.UseGenerics && Class.Template != null && Class.Template.IsGeneric) return;
            this.VisitAttributeList(Class.Attributes, Class);
            this.VisitSecurityAttributeList(Class.SecurityAttributes, Class);
            if (Class.BaseClass != null) this.VisitReferencedType(Class.BaseClass);
            for (int i = 0, n = Class.Interfaces == null ? 0 : Class.Interfaces.Count; i < n; i++)
            {
                this.GetTypeDefOrRefOrSpecEncoded(Class.Interfaces[i]);
                if (Class.Interfaces[i] != null) this.interfaceEntries.Add(Class);
            }
            if (Class.NodeType == NodeType.ClassParameter && !(Class is MethodClassParameter))
                this.interfaceEntries.Add(Class);
            for (int i = 0, n = Class.Members.Count; i < n; i++)
            {
                Member mem = Class.Members[i];
                if (mem == null || mem is TypeNode) continue;
                this.Visit(mem);
            }
            if ((Class.Flags & (TypeFlags.ExplicitLayout | TypeFlags.SequentialLayout)) != 0 && (Class.PackingSize != 0 || Class.ClassSize != 0))
                this.classLayoutEntries.Add(Class);
        }
        void VisitConstruct(Construct/*!*/ cons)
        {
            int pops = -1;
            ExpressionList operands = cons.Operands;
            if (operands != null)
            {
                this.VisitExpressionList(cons.Operands);
                pops = operands.Count - 1;
            }
            if (pops >= 0)
                this.stackHeight -= pops;
            else
                this.IncrementStackHeight();
            this.methodBodyHeap.Write((byte)0x73);
            Method method = ((MemberBinding)cons.Constructor).BoundMember as Method;
            if (method == null) return;
            this.methodBodyHeap.Write((int)this.GetMethodToken(method)); //REVIEW: varargs?
        }
        void VisitConstructArray(ConstructArray/*!*/ consArr)
        {
            if (consArr == null || consArr.Operands == null || consArr.Operands.Count < 1) return;
            this.Visit(consArr.Operands[0]);
            this.methodBodyHeap.Write((byte)0x8d);
            this.methodBodyHeap.Write((int)this.GetTypeToken(consArr.ElementType));
        }
        void VisitDelegateNode(DelegateNode/*!*/ delegateNode)
        {
            if (this.UseGenerics && delegateNode.Template != null && delegateNode.Template.IsGeneric) return;
            this.VisitAttributeList(delegateNode.Attributes, delegateNode);
            this.VisitSecurityAttributeList(delegateNode.SecurityAttributes, delegateNode);
            this.VisitReferencedType(CoreSystemTypes.MulticastDelegate);
            for (int i = 0, n = delegateNode.Interfaces == null ? 0 : delegateNode.Interfaces.Count; i < n; i++)
            { //REVIEW: is this valid?
                this.GetTypeDefOrRefOrSpecEncoded(delegateNode.Interfaces[i]);
                if (delegateNode.Interfaces[i] != null) this.interfaceEntries.Add(delegateNode);
            }
            for (int i = 0, n = delegateNode.Members.Count; i < n; i++)
            {
                Member mem = delegateNode.Members[i];
                if (mem == null || mem is TypeNode) continue;
                this.Visit(mem);
            }
        }
        void VisitEndFilter(EndFilter/*!*/ endFilter)
        {
            this.DefineSequencePoint(endFilter);
            this.Visit(endFilter.Value);
            this.methodBodyHeap.Write((byte)0xfe);
            this.methodBodyHeap.Write((byte)0x11);
            this.stackHeight--;
        }
        void VisitEnumNode(EnumNode/*!*/ enumNode)
        {
            this.VisitAttributeList(enumNode.Attributes, enumNode);
            this.VisitSecurityAttributeList(enumNode.SecurityAttributes, enumNode);
            this.VisitReferencedType(CoreSystemTypes.Enum);
            for (int i = 0, n = enumNode.Interfaces == null ? 0 : enumNode.Interfaces.Count; i < n; i++)
            {
                this.GetTypeDefOrRefOrSpecEncoded(enumNode.Interfaces[i]);
                if (enumNode.Interfaces[i] != null) this.interfaceEntries.Add(enumNode);
            }
            for (int i = 0, n = enumNode.Members.Count; i < n; i++)
                this.Visit(enumNode.Members[i]);
        }
        void VisitEvent(Event/*!*/ Event)
        {
            object eindex = this.eventIndex[Event.UniqueKey];
            if (eindex != null) return;
            int index = this.eventEntries.Count + 1;
            this.eventEntries.Add(Event);
            this.eventIndex[Event.UniqueKey] = index;
            object evindex = this.eventMapIndex[Event.DeclaringType.UniqueKey];
            if (evindex == null)
            {
                this.eventMapEntries.Add(Event);
                this.eventMapIndex[Event.DeclaringType.UniqueKey] = this.eventMapEntries.Count;
            }
            if (Event.HandlerAdder != null) this.methodSemanticsEntries.Add(Event);
            if (Event.HandlerRemover != null) this.methodSemanticsEntries.Add(Event);
            if (Event.HandlerCaller != null) this.methodSemanticsEntries.Add(Event);
            if (Event.OtherMethods != null)
                for (int i = 0, n = Event.OtherMethods.Count; i < n; i++)
                    this.methodSemanticsEntries.Add(Event);
            this.VisitAttributeList(Event.Attributes, Event);
        }
        void VisitExpression(Expression/*!*/ expression)
        {
            switch (expression.NodeType)
            {
                case NodeType.Dup:
                    this.methodBodyHeap.Write((byte)0x25);
                    this.IncrementStackHeight();
                    return;
                case NodeType.Pop:
                    UnaryExpression unex = expression as UnaryExpression;
                    if (unex != null)
                    {
                        this.Visit(unex.Operand);
                        this.stackHeight--;
                        this.methodBodyHeap.Write((byte)0x26);
                    }
                    return;
                case NodeType.Arglist:
                    this.IncrementStackHeight();
                    this.methodBodyHeap.Write((byte)0xfe);
                    this.methodBodyHeap.Write((byte)0x00);
                    return;
            }
        }
        void VisitExpressionList(ExpressionList expressions)
        {
            if (expressions == null) return;
            for (int i = 0, n = expressions.Count; i < n; i++)
                this.Visit(expressions[i]);
        }
        void VisitExpressionStatement(ExpressionStatement/*!*/ statement)
        {
#if !MinimalReader
            if (!(statement.Expression is BlockExpression))
#endif
                this.DefineSequencePoint(statement);
            this.Visit(statement.Expression);
        }
        void VisitField(Field/*!*/ field)
        {
            this.VisitAttributeList(field.Attributes, field);
            this.GetFieldIndex(field);
            if (field.IsVolatile)
                field.Type = RequiredModifier.For(CoreSystemTypes.IsVolatile, field.Type);
            this.VisitReferencedType(field.Type);
        }
        void VisitFixupList(Fixup fixup, int targetAddress)
        {
            while (fixup != null)
            {
                this.methodBodyHeap.BaseStream.Position = fixup.fixupLocation;
                if (fixup.shortOffset)
                {
                    int offset = targetAddress - fixup.addressOfNextInstruction;
                    Debug.Assert(-128 <= offset && offset <= 127, "Invalid short branch");
                    this.methodBodyHeap.Write((byte)offset);
                }
                else
                    this.methodBodyHeap.Write((int)(targetAddress - fixup.addressOfNextInstruction));
                fixup = fixup.nextFixUp;
            }
        }
        void VisitGenericParameterList(Member/*!*/ member, TypeNodeList/*!*/ parameters)
        {
            if (member == null || parameters == null || !this.UseGenerics) return;
            int sign = member is Method ? -1 : 1;
            for (int i = 0, n = parameters.Count; i < n; i++)
            {
                TypeNode parameter = parameters[i];
                if (parameter == null) continue;
                this.typeParameterNumber[parameter.UniqueKey] = sign * (i + 1);
                this.genericParamEntries.Add(member);
                if (((ITypeParameter)parameter).DeclaringMember != member)
                    parameter = (TypeNode)parameter.Clone();
                this.genericParameters.Add(parameter);
                if (parameter.BaseType is Class && parameter.BaseType != CoreSystemTypes.Object)
                    this.genericParamConstraintEntries.Add(parameter);
                for (int j = 0, m = parameter.Interfaces == null ? 0 : parameter.Interfaces.Count; j < m; j++)
                    this.genericParamConstraintEntries.Add(parameter);
            }
        }
        void VisitIndexer(Indexer/*!*/ indexer)
        {
            this.Visit(indexer.Object);
            if (indexer.Operands == null || indexer.Operands.Count < 1) return;
            this.Visit(indexer.Operands[0]);
            byte opCode;
            switch (indexer.ElementType.typeCode)
            {
                case ElementType.Boolean:
                case ElementType.Int8: opCode = 0x90; break;
                case ElementType.UInt8: opCode = 0x91; break;
                case ElementType.Int16: opCode = 0x92; break;
                case ElementType.Char:
                case ElementType.UInt16: opCode = 0x93; break;
                case ElementType.Int32: opCode = 0x94; break;
                case ElementType.UInt32: opCode = 0x95; break;
                case ElementType.Int64:
                case ElementType.UInt64: opCode = 0x96; break;
                case ElementType.UIntPtr:
                case ElementType.IntPtr: opCode = 0x97; break;
                case ElementType.Single: opCode = 0x98; break;
                case ElementType.Double: opCode = 0x99; break;
                default:
                    if (this.UseGenerics && indexer.ElementType is ITypeParameter)
                        opCode = 0xa3;
                    else if (TypeNode.StripModifiers(indexer.ElementType) is Pointer)
                        opCode = 0x97;
                    else
                        opCode = 0x9a;
                    break;
            }
            this.methodBodyHeap.Write((byte)opCode);
            if (opCode == 0xa3) this.methodBodyHeap.Write((int)this.GetTypeToken(indexer.ElementType));
            this.stackHeight--;
        }
        void VisitInterface(Interface/*!*/ Interface)
        {
            if (this.UseGenerics && Interface.Template != null && Interface.Template.IsGeneric) return;
            this.VisitAttributeList(Interface.Attributes, Interface);
            this.VisitSecurityAttributeList(Interface.SecurityAttributes, Interface);
            InterfaceList interfaces = Interface.Interfaces;
            for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
            {
                this.GetTypeDefOrRefOrSpecEncoded(interfaces[i]);
                if (interfaces[i] != null) this.interfaceEntries.Add(Interface);
            }
            if (Interface.NodeType == NodeType.TypeParameter && !(Interface is MethodTypeParameter))
                this.interfaceEntries.Add(Interface);
            for (int i = 0, n = Interface.Members.Count; i < n; i++)
            {
                Member mem = Interface.Members[i];
                if (mem == null || mem is TypeNode) continue;
                this.Visit(mem);
            }
        }
        void VisitLocal(Local/*!*/ local)
        {
            this.IncrementStackHeight();
            int li = this.GetLocalVarIndex(local);
            switch (li)
            {
                case 0: this.methodBodyHeap.Write((byte)0x06); return;
                case 1: this.methodBodyHeap.Write((byte)0x07); return;
                case 2: this.methodBodyHeap.Write((byte)0x08); return;
                case 3: this.methodBodyHeap.Write((byte)0x09); return;
                default:
                    if (li < 256)
                    {
                        this.methodBodyHeap.Write((byte)0x11);
                        this.methodBodyHeap.Write((byte)li);
                    }
                    else
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x0c);
                        this.methodBodyHeap.Write((ushort)li);
                    }
                    return;
            }
        }
#if !MinimalReader
        /// <summary>
        /// This just gets the local variable index for each local declaration.
        /// That associates the debug information with the right block because
        /// it is the block the local is declared in rather than the subblock
        /// it is first referenced in. (When different, the debugger only knows
        /// about the local when control is in the subblock.)
        /// </summary>
        /// <param name="localDeclarations">The list of locals declared at this statement</param>
        void VisitLocalDeclarationsStatement(LocalDeclarationsStatement/*!*/ localDeclarations)
        {
            if (localDeclarations == null) return;
            LocalDeclarationList decls = localDeclarations.Declarations;
            for (int i = 0, n = decls == null ? 0 : decls.Count; i < n; i++)
            {
                //^ assert decls != null;
                LocalDeclaration decl = decls[i];
                if (decl == null) continue;
                Field f = decl.Field;
                if (f == null) continue;
                //^ assume this.currentMethod != null;
                Local loc = this.currentMethod.GetLocalForField(f);
                loc.Type = localDeclarations.Type;
                this.GetLocalVarIndex(loc);
            }
        }
#endif
        void VisitLiteral(Literal/*!*/ literal)
        {
            this.IncrementStackHeight();
            IConvertible ic = literal.Value as IConvertible;
            if (ic == null)
            {
                Debug.Assert(literal.Value == null && !literal.Type.IsValueType);
                this.methodBodyHeap.Write((byte)0x14); return;
            }
            TypeCode tc = ic.GetTypeCode();
            switch (tc)
            {
                case TypeCode.Boolean:
                case TypeCode.SByte:
                case TypeCode.Byte:
                case TypeCode.Char:
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                    long n = ic.ToInt64(null);
                    switch (n)
                    {
                        case -1: this.methodBodyHeap.Write((byte)0x15); break;
                        case 0: this.methodBodyHeap.Write((byte)0x16); break;
                        case 1: this.methodBodyHeap.Write((byte)0x17); break;
                        case 2: this.methodBodyHeap.Write((byte)0x18); break;
                        case 3: this.methodBodyHeap.Write((byte)0x19); break;
                        case 4: this.methodBodyHeap.Write((byte)0x1a); break;
                        case 5: this.methodBodyHeap.Write((byte)0x1b); break;
                        case 6: this.methodBodyHeap.Write((byte)0x1c); break;
                        case 7: this.methodBodyHeap.Write((byte)0x1d); break;
                        case 8: this.methodBodyHeap.Write((byte)0x1e); break;
                        default:
                            if (n >= System.SByte.MinValue && n <= System.SByte.MaxValue)
                            {
                                this.methodBodyHeap.Write((byte)0x1f);
                                this.methodBodyHeap.Write((byte)n);
                            }
                            else if (n >= System.Int32.MinValue && n <= System.Int32.MaxValue ||
                              n <= System.UInt32.MaxValue && (tc == TypeCode.Char || tc == TypeCode.UInt16 || tc == TypeCode.UInt32))
                            {
                                if (n == System.UInt32.MaxValue && tc != TypeCode.Int64)
                                    this.methodBodyHeap.Write((byte)0x15);
                                else
                                {
                                    this.methodBodyHeap.Write((byte)0x20);
                                    this.methodBodyHeap.Write((int)n);
                                }
                            }
                            else
                            {
                                this.methodBodyHeap.Write((byte)0x21);
                                this.methodBodyHeap.Write((long)n);
                                tc = TypeCode.Empty; //Suppress conversion to long
                            }
                            break;
                    }
                    if (tc == TypeCode.Int64)
                        this.methodBodyHeap.Write((byte)0x6a);
                    return;

                case TypeCode.UInt64:
                    this.methodBodyHeap.Write((byte)0x21);
                    this.methodBodyHeap.Write(ic.ToUInt64(null));
                    return;

                case TypeCode.Single:
                    this.methodBodyHeap.Write((byte)0x22);
                    this.methodBodyHeap.Write(ic.ToSingle(null));
                    return;

                case TypeCode.Double:
                    this.methodBodyHeap.Write((byte)0x23);
                    this.methodBodyHeap.Write(ic.ToDouble(null));
                    return;

                case TypeCode.String:
                    this.methodBodyHeap.Write((byte)0x72);
                    this.methodBodyHeap.Write((int)(this.GetUserStringIndex((String)literal.Value) | 0x70000000));
                    return;
            }
            Debug.Assert(false, "Unexpected literal type");
        }
        void VisitMemberBinding(MemberBinding/*!*/ memberBinding)
        {
            if (memberBinding.TargetObject != null)
            {
                this.Visit(memberBinding.TargetObject);
                if (memberBinding.Volatile)
                {
                    this.methodBodyHeap.Write((byte)0xfe);
                    this.methodBodyHeap.Write((byte)0x13);
                }
                this.methodBodyHeap.Write((byte)0x7b);
            }
            else
            {
                this.IncrementStackHeight();
                if (memberBinding.Volatile)
                {
                    this.methodBodyHeap.Write((byte)0xfe);
                    this.methodBodyHeap.Write((byte)0x13);
                }
                this.methodBodyHeap.Write((byte)0x7e);
            }
            this.methodBodyHeap.Write((int)this.GetFieldToken((Field)memberBinding.BoundMember));
            return;
        }
        void VisitMethod(Method/*!*/ method)
        {
            if (this.UseGenerics && method.Template != null && method.Template.IsGeneric) return;
            this.GetMethodIndex(method);
            this.VisitAttributeList(method.Attributes, method);
            this.VisitSecurityAttributeList(method.SecurityAttributes, method);
            for (int i = 0, n = method.Parameters == null ? 0 : method.Parameters.Count; i < n; i++)
            {
                Parameter par = method.Parameters[i];
                if (par == null) continue;
                this.VisitAttributeList(par.Attributes, par);
                this.VisitReferencedType(par.Type);
            }
            if (method.ReturnType != null)
                this.VisitReferencedType(method.ReturnType);
            if (!method.IsAbstract && method.Body != null)
            {
                if (method.Body.Statements != null && method.Body.Statements.Count > 0)
                    this.VisitMethodBody(method);
            }
            MethodList implementedInterfaceMethods = method.ImplementedInterfaceMethods;
            for (int i = 0, n = implementedInterfaceMethods == null ? 0 : implementedInterfaceMethods.Count; i < n; i++)
            {
                Method im = implementedInterfaceMethods[i];
                if (im == null) continue;
                this.methodImplEntries.Add(method);
            }
            if ((method.Flags & MethodFlags.PInvokeImpl) != 0 && method.PInvokeImportName != null && method.PInvokeModule != null)
            {
                this.implMapEntries.Add(method);
                this.GetStringIndex(method.PInvokeImportName);
                this.GetModuleRefIndex(method.PInvokeModule);
            }
        }
        void VisitMethodBody(Method/*!*/ method)
        {
            //Visit body, emitting IL bytes and gathering information
            this.methodBodyHeap = new BinaryWriter(new MemoryStream());
            this.methodInfo = new MethodInfo();
            this.currentMethod = method;
            this.stackHeightMax = 0;
            this.stackHeightExitTotal = 0;
#if !ROTOR
            if (this.symWriter != null)
            {
                this.methodInfo.debugLocals = new LocalList();
                this.methodInfo.signatureLengths = new Int32List();
                this.methodInfo.signatureOffsets = new Int32List();
                this.methodInfo.statementNodes = new NodeList();
                this.methodInfo.statementOffsets = new Int32List();
                this.symWriter.OpenMethod((uint)this.GetMethodDefToken(method));
                this.symWriter.OpenScope(0u);
#if !MinimalReader
                MethodScope scope = method.Scope;
                if (scope != null)
                {
                    UsedNamespaceList usedNamespaces = scope.UsedNamespaces;
                    for (int i = 0, n = usedNamespaces == null ? 0 : usedNamespaces.Count; i < n; i++)
                    {
                        //^ assert usedNamespaces != null;
                        UsedNamespace uns = usedNamespaces[i];
                        if (uns == null || uns.Namespace == null) continue;
                        this.symWriter.UsingNamespace(uns.Namespace.ToString());
                    }
                }
#endif
            }
#endif
#if !FxCop
            int originalAddress = 0;
            if (method.LocalList != null)
            {
                for (int i = 0, n = method.LocalList.Count; i < n; i++)
                {
                    Local loc = method.LocalList[i];
                    if (loc == null) continue;
                    this.GetLocalVarIndex(loc);
                }
#if !ROTOR
                if (this.symWriter != null)
                {
                    int currentAddress = (int)this.methodBodyHeap.BaseStream.Position;
                    originalAddress = currentAddress;
                    this.symWriter.OpenScope((uint)currentAddress);
                }
#endif
            }
#endif
            int exceptionHandlersCount = method.ExceptionHandlers == null ? 0 : method.ExceptionHandlers.Count;
            if (exceptionHandlersCount > 0)
            {
                this.exceptionBlock = new TrivialHashtable();
                for (int i = 0; i < exceptionHandlersCount; i++)
                {
                    ExceptionHandler eh = method.ExceptionHandlers[i];
                    if (eh == null || eh.HandlerStartBlock == null || (eh.HandlerType != NodeType.Catch && eh.HandlerType != NodeType.Filter)) continue;
                    this.exceptionBlock[eh.HandlerStartBlock.UniqueKey] = eh;
                }
            }
            this.VisitBlock(method.Body);

#if !FxCop
            if (method.LocalList != null)
            {
#if !ROTOR
                if (this.symWriter != null)
                {
                    DefineLocalVariables(originalAddress, method.LocalList);
                }
#endif
            }
#endif

            this.methodBodiesHeapIndex[method.UniqueKey] = (int)this.methodBodiesHeap.BaseStream.Position;
            int maxStack = this.stackHeightExitTotal + this.stackHeightMax; //Wildly pessimistic estimate. Works dandy if BBlocks never leave anything on the stack.
            if (exceptionHandlersCount > 0 && maxStack == 0) maxStack = 1;
            int codeSize = (int)this.methodBodyHeap.BaseStream.Position;
            int localVarSigTok = this.methodInfo.localVarSigTok;
            bool fatHeader = codeSize >= 64 || exceptionHandlersCount > 0 || maxStack > 8 || localVarSigTok != 0;
            if (fatHeader)
            {
                //Emit fat header
                byte header = 0x03;
                if (method.InitLocals) header |= 0x10;
                if (exceptionHandlersCount > 0) header |= 0x08;
                this.methodBodiesHeap.Write((byte)header);
                this.methodBodiesHeap.Write((byte)0x30); //top 4 bits represent length of fat header in dwords. Heaven only knows why.
                this.methodBodiesHeap.Write((short)maxStack);
                this.methodBodiesHeap.Write((int)codeSize);
                if (localVarSigTok != 0)
                {
                    if (this.methodInfo.localVarIndex.Count > 127)
                    {
                        //Need to make space for the two byte count
                        this.methodInfo.localVarSignature.Write((byte)0);
                        byte[] buf = this.methodInfo.localVarSignature.BaseStream.Buffer;
                        int n = buf.Length;
                        for (int i = n - 2; i > 1; i--) buf[i + 1] = buf[i];
                    }
                    this.methodInfo.localVarSignature.BaseStream.Position = 0;
                    this.methodInfo.localVarSignature.Write((byte)7);
                    Ir2md.WriteCompressedInt(this.methodInfo.localVarSignature, this.methodInfo.localVarIndex.Count);
                    Debug.Assert(this.methodInfo.localVarIndex.Count <= 0xFFFE);
                }
                this.methodBodiesHeap.Write((int)localVarSigTok);
            }
            else
            {
                //Emit tiny header
                this.methodBodiesHeap.Write((byte)(codeSize << 2 | 2));
            }
            //Copy body to bodies heap
            ((MemoryStream)this.methodBodyHeap.BaseStream).WriteTo(this.methodBodiesHeap.BaseStream);
            int pad = (int)this.methodBodiesHeap.BaseStream.Position;
            while (pad % 4 != 0) { pad++; this.methodBodiesHeap.Write((byte)0); }
            if (fatHeader)
            {
                //Emit exception handler entries
                int[] tryOffsets = new int[exceptionHandlersCount];
                int[] tryLengths = new int[exceptionHandlersCount];
                int[] handlerOffsets = new int[exceptionHandlersCount];
                int[] handlerLengths = new int[exceptionHandlersCount];
                bool fatFormat = false;
                for (int i = 0; i < exceptionHandlersCount; i++)
                {
                    ExceptionHandler eh = method.ExceptionHandlers[i];
                    int tryOffset = tryOffsets[i] = (int)this.methodInfo.fixupIndex[eh.TryStartBlock.UniqueKey];
                    int tryLength = tryLengths[i] = ((int)this.methodInfo.fixupIndex[eh.BlockAfterTryEnd.UniqueKey]) - tryOffset;
                    int handlerOffset = handlerOffsets[i] = (int)this.methodInfo.fixupIndex[eh.HandlerStartBlock.UniqueKey];
                    int handlerLength = handlerLengths[i] = ((int)this.methodInfo.fixupIndex[eh.BlockAfterHandlerEnd.UniqueKey]) - handlerOffset;
                    if (tryOffset > 0xffff || tryLength > 0xff || handlerOffset > 0xffff || handlerLength > 0xff) fatFormat = true;
                }
                if (exceptionHandlersCount * 12 > 0xff) fatFormat = true;
                if (fatFormat)
                {
                    int dataSize = exceptionHandlersCount * 24 + 4;
                    this.methodBodiesHeap.Write((byte)0x41);
                    this.methodBodiesHeap.Write((byte)(dataSize & 0xff));
                    this.methodBodiesHeap.Write((short)((dataSize >> 8) & 0xffff));
                }
                else
                {
                    int dataSize = exceptionHandlersCount * 12 + 4;
                    this.methodBodiesHeap.Write((byte)0x01);
                    this.methodBodiesHeap.Write((byte)dataSize);
                    this.methodBodiesHeap.Write((short)0);
                }
                for (int i = 0; i < exceptionHandlersCount; i++)
                {
                    ExceptionHandler eh = method.ExceptionHandlers[i];
                    byte flags = 0;
                    switch (eh.HandlerType)
                    {
                        case NodeType.Filter: flags = 0x0001; break;
                        case NodeType.Finally: flags = 0x0002; break;
                        case NodeType.FaultHandler: flags = 0x0004; break;
                    }
                    if (fatFormat)
                    {
                        this.methodBodiesHeap.Write((int)flags);
                        this.methodBodiesHeap.Write((int)tryOffsets[i]);
                        this.methodBodiesHeap.Write((int)tryLengths[i]);
                        this.methodBodiesHeap.Write((int)handlerOffsets[i]);
                        this.methodBodiesHeap.Write((int)handlerLengths[i]);
                    }
                    else
                    {
                        this.methodBodiesHeap.Write((short)flags);
                        this.methodBodiesHeap.Write((ushort)tryOffsets[i]);
                        this.methodBodiesHeap.Write((byte)tryLengths[i]);
                        this.methodBodiesHeap.Write((ushort)handlerOffsets[i]);
                        this.methodBodiesHeap.Write((byte)handlerLengths[i]);
                    }
                    if (eh.FilterType != null)
                        this.methodBodiesHeap.Write((int)this.GetTypeToken(eh.FilterType));
                    else if (eh.FilterExpression != null)
                        this.methodBodiesHeap.Write((int)this.methodInfo.fixupIndex[eh.FilterExpression.UniqueKey]);
                    else
                        this.methodBodiesHeap.Write((int)0);
                }
            }
#if !ROTOR
            if (this.symWriter != null)
            {
                MethodInfo mInfo = this.methodInfo;
                NodeList statementNodes = mInfo.statementNodes;
                Int32List statementOffsets = mInfo.statementOffsets;
                int n = statementNodes.Count;
                int j = 0;
                int k = 0;
                Document d = null;
                ISymUnmanagedDocumentWriter doc = null;
                for (int i = 0; i < n; i++)
                {
                    Document e = statementNodes[i].SourceContext.Document;
                    if (e == null) continue;
                    if (e != d)
                    {
                        d = e;
                        if (doc != null) this.DefineSequencePoints(statementNodes, statementOffsets, j, k, doc);
                        doc = this.GetDocumentWriter(d);
                        j = i;
                        k = 0;
                    }
                    k++;
                }
                this.DefineSequencePoints(statementNodes, statementOffsets, j, k, doc);
                this.symWriter.CloseScope((uint)this.methodBodyHeap.BaseStream.Position);
                this.symWriter.CloseMethod();
            }
#endif
            //this.methodBodyHeap = null;
            //this.methodInfo = null;
            //this.currentMethod = null;
        }

#if !ROTOR
        private void DefineLocalVariables(int startAddress, LocalList locals)
        {
            MethodInfo mInfo = this.methodInfo;
            for (int i = 0, n = locals.Count; i < n; i++)
            {
                Local loc = locals[i];
                string name = loc.Name.ToString();
                unsafe
                {
                    fixed (byte* p = mInfo.localVarSignature.BaseStream.Buffer)
                    {
                        IntPtr sp = (IntPtr)(p + mInfo.signatureOffsets[i]);
                        uint c = (uint)mInfo.signatureLengths[i];
                        this.symWriter.DefineLocalVariable(name, 0u, c, sp, 1u, (uint)this.GetLocalVarIndex(loc), 0u, 0u, 0u);
                    }
                }
            }
            int posOfFirstInstructionOfNextBlock = this.methodBodyHeap.BaseStream.Position;
            if (posOfFirstInstructionOfNextBlock > startAddress)
                this.symWriter.CloseScope((uint)(posOfFirstInstructionOfNextBlock - 1));
            else
                this.symWriter.CloseScope((uint)startAddress);
        }
#endif
        void DefineSequencePoint(Node node)
        {
#if !ROTOR
            if (this.symWriter != null && node != null && node.SourceContext.Document != null && !node.SourceContext.Document.Hidden)
            {
                this.methodInfo.statementNodes.Add(node);
                this.methodInfo.statementOffsets.Add(this.methodBodyHeap.BaseStream.Position);
            }
#endif
        }
#if !ROTOR
        void DefineSequencePoints(NodeList/*!*/ statementNodes, Int32List/*!*/ statementOffsets, int start, int count, ISymUnmanagedDocumentWriter doc)
        //^ requires this.symWriter != null;
        {
            if (count == 0) return;
            uint[] offsets = new uint[count];
            uint[] lines = new uint[count];
            uint[] columns = new uint[count];
            uint[] endLines = new uint[count];
            uint[] endColumns = new uint[count];
            for (int i = 0; i < count; i++)
            {
                Node n = statementNodes[i + start];
                offsets[i] = i + start == 0 ? 0 : (uint)statementOffsets[i + start];
                lines[i] = (uint)n.SourceContext.StartLine;
                columns[i] = (uint)n.SourceContext.StartColumn;
                endLines[i] = (uint)n.SourceContext.EndLine;
                endColumns[i] = (uint)n.SourceContext.EndColumn;
            }
            this.symWriter.DefineSequencePoints(doc, (uint)count, offsets, lines, columns, endLines, endColumns);
        }
#endif
        void VisitModule(Module/*!*/ module)
        {
            //REVIEW: check that module has no explicit lists of assembly/module references?
            this.ForceTemplateTypeMethodBodiesToGetSpecialized(module);
            this.VisitAttributeList(module.Attributes, module);
            if (this.assembly != null)
            {
                Module m = new Module();
                m.Attributes = this.assembly.ModuleAttributes;
                this.VisitAttributeList(m.Attributes, m);
                this.VisitSecurityAttributeList(this.assembly.SecurityAttributes, this.assembly);
            }
            TypeNodeList allTypes = module.Types.Clone();
            for (int k = 0; k < allTypes.Count; )
            {
                int typeCount = module.Types.Count;
                for (int i = k, n = k, m = allTypes.Count; i < (n = allTypes.Count); )
                {
                    for (; i < n; i++)
                    {
                        TypeNode t = allTypes[i];
                        if (t == null) continue;
                        if (this.UseGenerics && t.Template != null && t.Template.IsGeneric)
                        {
                            allTypes[i] = null;
                            continue;
                        }
                        this.GetTypeDefIndex(t);
                        if (i >= m) this.nestedClassEntries.Add(t);
                        MemberList members = t.Members;
                        if (members != null)
                        {
                            for (int j = 0, numMembers = members.Count; j < numMembers; j++)
                            {
                                TypeNode nt = members[j] as TypeNode;
                                if (nt != null) allTypes.Add(nt);
                            }
                        }
                    }
                }
                for (int i = k, n = allTypes.Count; i < n; i++)
                {
                    TypeNode t = allTypes[i];
                    if (t == null) continue;
                    if (this.UseGenerics && t.Template != null && t.Template.IsGeneric)
                    {
                        allTypes[i] = null;
                        continue;
                    }
                    MemberList mems = t.Members;
                    if (t is EnumNode)
                    { //Work around JIT bug in Beta2
                        for (int jj = 0, mm = mems.Count; jj < mm; jj++)
                        {
                            Field f = mems[jj] as Field;
                            if (f == null || f.IsStatic) continue;
                            mems[jj] = mems[0];
                            mems[0] = f;
                            break;
                        }
                    }
                    for (int j = 0, m = mems.Count; j < m; j++)
                    {
                        Member mem = mems[j];
                        if (mem == null) continue;
                        switch (mem.NodeType)
                        {
                            case NodeType.Field: this.GetFieldIndex((Field)mem); break;
                            case NodeType.Method:
                            case NodeType.InstanceInitializer:
                            case NodeType.StaticInitializer:
                                Method meth = (Method)mem;
                                if (this.UseGenerics && meth.Template != null && meth.Template.IsGeneric)
                                    this.GetMethodSpecIndex(meth);
                                else
                                    this.GetMethodIndex(meth);
                                break;
                        }
                    }
                }
                for (int i = k, n = allTypes.Count; i < n; i++, k++)
                {
                    TypeNode t = allTypes[i];
                    if (t == null) continue;
                    this.Visit(t);
                }
                for (int i = typeCount, n = module.Types.Count; i < n; i++)
                {
                    TypeNode t = module.Types[i];
                    if (t == null) continue;
                    Debug.Assert(t.IsNotFullySpecialized);
                    //allTypes.Add(t);
                }
            }
        }
        sealed class MethodSpecializer : StandardVisitor
        {
            private Module/*!*/ module;

            internal MethodSpecializer(Module/*!*/ module)
            {
                this.module = module;
                //^ base();
            }

            public override Method VisitMethod(Method method)
            {
                if (method == null) return null;
                if (method.Template == null || method.Template.IsGeneric) return method;
                TypeNodeList templateParameters = null;
                TypeNodeList templateArguments = null;
                if (method.TemplateArguments != null && method.TemplateArguments.Count > 0)
                {
                    templateParameters = method.Template.TemplateParameters;
                    templateArguments = method.TemplateArguments;
                }
                else
                {
                    TypeNode tdt = method.Template.DeclaringType;
                    TypeNode dt = method.DeclaringType;
                    templateParameters = tdt.ConsolidatedTemplateParameters;
                    templateArguments = dt.ConsolidatedTemplateArguments;
                    if (templateArguments == null) templateArguments = templateParameters;
                }
                if (templateParameters == null || templateParameters.Count == 0) return method;
                TypeNode declaringTemplate = method.DeclaringType == null ? null : method.DeclaringType.Template;
                bool savedNewTemplateInstanceIsRecursive = false;
                if (declaringTemplate != null)
                {
                    savedNewTemplateInstanceIsRecursive = declaringTemplate.NewTemplateInstanceIsRecursive;
                    declaringTemplate.NewTemplateInstanceIsRecursive = method.DeclaringType.IsNotFullySpecialized;
                }
                Duplicator duplicator = new Duplicator(this.module, method.DeclaringType);
#if !MinimalReader
                TypeNode closureClone = null;
                if (method.Template.Scope != null && method.Template.Scope.CapturedForClosure)
                {
                    duplicator.TypesToBeDuplicated[method.Template.Scope.ClosureClass.UniqueKey] = method.Template.Scope.ClosureClass;
                    duplicator.RecordOriginalAsTemplate = true;
                    closureClone = duplicator.VisitTypeNode(method.Template.Scope.ClosureClass);
                }
#endif
                int n = method.Parameters == null ? 0 : method.Parameters.Count;
                int m = method.Template.Parameters == null ? 0 : method.Template.Parameters.Count;
                if (n != m) { Debug.Assert(false); if (n > m) n = m; }
                for (int i = 0; i < n; i++)
                {
                    Parameter par = method.Parameters[i];
                    Parameter tpar = method.Template.Parameters[i];
                    if (par == null || tpar == null) continue;
                    duplicator.DuplicateFor[tpar.UniqueKey] = par;
                }
                n = method.TemplateParameters == null ? 0 : method.TemplateParameters.Count;
                m = method.Template.TemplateParameters == null ? 0 : method.Template.TemplateParameters.Count;
                if (n != m && n > 0) { Debug.Assert(false); if (n > m) n = m; }
                for (int i = 0; i < n; i++)
                {
                    TypeNode tpar = method.TemplateParameters[i];
                    TypeNode ttpar = method.Template.TemplateParameters[i];
                    if (tpar == null || ttpar == null) continue;
                    duplicator.DuplicateFor[ttpar.UniqueKey] = tpar;
                }
                Method dup = duplicator.VisitMethod(method.Template);
                //^ assume dup != null;
                Specializer specializer = new Specializer(this.module, templateParameters, templateArguments);
                specializer.VisitMethod(dup);
#if !MinimalReader
                if (closureClone != null)
                {
                    specializer.VisitTypeNode(closureClone);
                    if (method.TemplateArguments != null && method.TemplateArguments.Count > 0)
                        closureClone.Name = Identifier.For(closureClone.Name.ToString() + closureClone.UniqueKey);
                    MemberList dtMembers = method.DeclaringType.Members;
                    for (int i = 0, nmems = dtMembers == null ? 0 : dtMembers.Count; i < nmems; i++)
                    {
                        ClosureClass closureRef = dtMembers[i] as ClosureClass;
                        if (closureRef != null && closureRef.Name.UniqueIdKey == closureClone.Name.UniqueIdKey)
                        {
                            //This happens when the declaring type was instantiated after Normalizer has already injected a closure into the template
                            dtMembers[i] = closureClone;
                            closureClone = null;
                            break;
                        }
                    }
                    if (closureClone != null)
                        method.DeclaringType.Members.Add(closureClone);
                }
#endif
                if (method.Template.DeclaringType.DeclaringModule != this.module)
                {
                    //Dealing with imported IR that misses important type information if it contains explicit stack operations (push, pop, dup) 
                    //Call a helper visitor to remove these stack operations and in the process supply the missing type information.
                    Unstacker unstacker = new Unstacker();
                    unstacker.Visit(dup);
                }
                MethodBodySpecializer mbSpecializer = this.module.GetMethodBodySpecializer(templateParameters, templateArguments);
                mbSpecializer.methodBeingSpecialized = method;
                mbSpecializer.dummyMethod = dup;
                mbSpecializer.VisitMethod(dup);
                method.Body = dup.Body;
                // HACK to try to fix parameter declaring method back to the way it was before:
                method.Parameters = method.Parameters;
                method.ExceptionHandlers = dup.ExceptionHandlers;
                if (declaringTemplate != null)
                    declaringTemplate.NewTemplateInstanceIsRecursive = savedNewTemplateInstanceIsRecursive;
                return method;
            }
        }
        void ForceTemplateTypeMethodBodiesToGetSpecialized(Module/*!*/ module)
        {
            MethodSpecializer visitor = new MethodSpecializer(module);
            if (module == null) return;
            TypeNodeList types = module.Types;
            if (types == null) return;
            for (int i = 0; i < types.Count; i++)
                this.ForceTemplateTypeMethodBodiesToGetSpecialized(types[i], visitor);
        }
        void ForceTemplateTypeMethodBodiesToGetSpecialized(TypeNode/*!*/ type, MethodSpecializer/*!*/ visitor)
        {
            if (type == null) return;
            if (type.IsNotFullySpecialized || type.IsGeneric) return;
            bool savedNewTemplateInstanceIsRecursive = type.NewTemplateInstanceIsRecursive;
            type.NewTemplateInstanceIsRecursive = type.IsNotFullySpecialized;
            MemberList members = type.Members;
            if (members == null) return;
            for (int j = 0; j < members.Count; j++)
            {
                Member mem = members[j];
                if (mem == null) continue;
                TypeNode t = mem as TypeNode;
                if (t != null)
                    this.ForceTemplateTypeMethodBodiesToGetSpecialized(t, visitor);
                else
                    visitor.VisitMethod(mem as Method);
            }
            type.NewTemplateInstanceIsRecursive = savedNewTemplateInstanceIsRecursive;
        }
        void VisitParameter(Parameter/*!*/ parameter)
        {
            this.IncrementStackHeight();
#if !MinimalReader
            ParameterBinding pb = parameter as ParameterBinding;
            if (pb != null) parameter = pb.BoundParameter;
#endif
            int pi = parameter.ArgumentListIndex;
            switch (pi)
            {
                case 0: this.methodBodyHeap.Write((byte)0x02); return;
                case 1: this.methodBodyHeap.Write((byte)0x03); return;
                case 2: this.methodBodyHeap.Write((byte)0x04); return;
                case 3: this.methodBodyHeap.Write((byte)0x05); return;
                default:
                    if (pi < 256)
                    {
                        this.methodBodyHeap.Write((byte)0x0e);
                        this.methodBodyHeap.Write((byte)pi);
                    }
                    else
                    {
                        this.methodBodyHeap.Write((byte)0xfe);
                        this.methodBodyHeap.Write((byte)0x09);
                        this.methodBodyHeap.Write((ushort)pi);
                    }
                    return;
            }
        }
        void VisitProperty(Property/*!*/ property)
        {
            object pindex = this.propertyIndex[property.UniqueKey];
            if (pindex != null) return;
            int index = this.propertyEntries.Count + 1;
            this.propertyEntries.Add(property);
            this.propertyIndex[property.UniqueKey] = index;
            object pmindex = this.propertyMapIndex[property.DeclaringType.UniqueKey];
            if (pmindex == null)
            {
                this.propertyMapEntries.Add(property);
                this.propertyMapIndex[property.DeclaringType.UniqueKey] = this.propertyMapEntries.Count;
            }
            if (property.Getter != null) this.methodSemanticsEntries.Add(property);
            if (property.Setter != null) this.methodSemanticsEntries.Add(property);
            if (property.OtherMethods != null)
                for (int i = 0, n = property.OtherMethods.Count; i < n; i++)
                    this.methodSemanticsEntries.Add(property);
            this.VisitAttributeList(property.Attributes, property);
        }
        void VisitReferencedType(TypeNode type)
        {
            if (type == null) return;
            if (type.IsGeneric && type.Template == null)
            {
                TypeNodeList templParams = type.ConsolidatedTemplateParameters;
                for (int i = 0, n = templParams == null ? 0 : templParams.Count; i < n; i++)
                    this.typeParameterNumber[templParams[i].UniqueKey] = i + 1;
            }
            switch (type.typeCode)
            {
                case ElementType.Pointer: this.VisitReferencedType(((Pointer)type).ElementType); return;
                case ElementType.Reference: this.VisitReferencedType(((Reference)type).ElementType); return;
                case ElementType.Array:
                case ElementType.SzArray: this.VisitReferencedType(((ArrayType)type).ElementType); return;
                case ElementType.OptionalModifier:
                case ElementType.RequiredModifier:
                    TypeModifier tm = (TypeModifier)type;
                    this.VisitReferencedType(tm.Modifier);
                    this.VisitReferencedType(tm.ModifiedType);
                    return;
                case ElementType.FunctionPointer:
                    FunctionPointer fp = (FunctionPointer)type;
                    this.VisitReferencedType(fp.ReturnType);
                    for (int i = 0, n = fp.ParameterTypes == null ? 0 : fp.ParameterTypes.Count; i < n; i++)
                        this.VisitReferencedType(fp.ParameterTypes[i]);
                    return;
                case ElementType.ValueType:
                case ElementType.Class:
                    break;
                default:
                    return;
            }
            if (this.IsStructural(type))
                this.GetTypeSpecIndex(type);
            else if (type.DeclaringModule == this.module)
                this.GetTypeDefIndex(type);
            else if (type.DeclaringModule != null)
                this.GetTypeRefIndex(type);
            else if (type.typeCode == ElementType.ValueType || type.typeCode == ElementType.Class)
            {
                //Get here for type parameters
                if (this.UseGenerics && this.typeParameterNumber[type.UniqueKey] != null) return;
                type.DeclaringModule = this.module;
                this.GetTypeDefIndex(type);
            }
            else
                Debug.Assert(false);
        }
        void VisitReturn(Return/*!*/ Return)
        {
            this.DefineSequencePoint(Return);
            if (Return.Expression != null)
            {
                this.Visit(Return.Expression);
                this.stackHeight--;
            }
            this.methodBodyHeap.Write((byte)0x2a);
        }
        void VisitSecurityAttributeList(SecurityAttributeList attrs, Node/*!*/ node)
        {
            if (attrs == null) return;
            int n = attrs.Count;
            if (n == 0) return;
            int m = n;
            for (int j = 0; j < n; j++)
            {
                SecurityAttribute a = attrs[j];
                if (a == null) m--;
            }
            if (m == 0) return;
            n = m;
            int codedIndex = this.GetSecurityAttributeParentCodedIndex(node);
            this.securityAttributeCount += n;
            m = this.nodesWithSecurityAttributes.Count;
            this.nodesWithSecurityAttributes.Add(node);
            int i = 0; //after the for loop i will be position where the new node should be in sorted list
            NodeList nodes = this.nodesWithSecurityAttributes;
            for (i = m; i > 0; i--)
            {
                Node other = nodes[i - 1];
                int oci = this.GetSecurityAttributeParentCodedIndex(other);
                if (oci < codedIndex) break;
            }
            if (i == m) return; //node is already where it should be
            for (int j = m; j > i; j--) nodes[j] = nodes[j - 1]; //Make space at postion i
            nodes[i] = node;
        }
        void VisitStatement(Statement/*!*/ statement)
        {
            this.DefineSequencePoint(statement);
            switch (statement.NodeType)
            {
                case NodeType.Nop: this.methodBodyHeap.Write((byte)0x00); break;
                case NodeType.DebugBreak: this.methodBodyHeap.Write((byte)0x01); break;
                case NodeType.EndFinally: this.methodBodyHeap.Write((byte)0xdc); break;
            }
        }
        void VisitStruct(Struct/*!*/ Struct)
        {
            if (this.UseGenerics && Struct.Template != null && Struct.Template.IsGeneric) return;
            this.VisitAttributeList(Struct.Attributes, Struct);
            this.VisitSecurityAttributeList(Struct.SecurityAttributes, Struct);
            this.VisitReferencedType(CoreSystemTypes.ValueType);
            InterfaceList interfaces = Struct.Interfaces;
            for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
            {
                this.GetTypeDefOrRefOrSpecEncoded(interfaces[i]);
                if (interfaces[i] != null) this.interfaceEntries.Add(Struct);
            }
            for (int i = 0, n = Struct.Members.Count; i < n; i++)
            {
                Member m = Struct.Members[i];
                if (m is TypeNode) continue;
                this.Visit(m);
            }
            if ((Struct.Flags & (TypeFlags.ExplicitLayout | TypeFlags.SequentialLayout)) != 0 && (Struct.PackingSize != 0 || Struct.ClassSize != 0))
                this.classLayoutEntries.Add(Struct);
        }
        void VisitSwitchInstruction(SwitchInstruction/*!*/ switchInstruction)
        {
            this.Visit(switchInstruction.Expression);
            this.stackHeight--;
            BlockList targets = switchInstruction.Targets;
            int n = targets != null ? targets.Count : 0;
            int addressOfNextInstruction = ((int)this.methodBodyHeap.BaseStream.Position) + 5 + 4 * n;
            this.methodBodyHeap.Write((byte)0x45);
            this.methodBodyHeap.Write((uint)n);
            for (int i = 0; i < n; i++)
                this.methodBodyHeap.Write((int)this.GetOffset(targets[i], addressOfNextInstruction));
        }
        void VisitTernaryExpression(TernaryExpression/*!*/ expression)
        {
            this.Visit(expression.Operand1);
            this.Visit(expression.Operand2);
            this.Visit(expression.Operand3);
            this.methodBodyHeap.Write((byte)0xfe);
            if (expression.NodeType == NodeType.Cpblk)
                this.methodBodyHeap.Write((byte)0x17);
            else
                this.methodBodyHeap.Write((byte)0x18);
            this.stackHeight -= 3;
        }
        void VisitThis(This/*!*/ This)
        {
            this.IncrementStackHeight();
            this.methodBodyHeap.Write((byte)0x02);
        }
        void VisitThrow(Throw/*!*/ Throw)
        {
            this.DefineSequencePoint(Throw);
            if (Throw.NodeType == NodeType.Rethrow)
            {
                this.methodBodyHeap.Write((byte)0xfe);
                this.methodBodyHeap.Write((byte)0x1a);
            }
            else
            {
                this.Visit(Throw.Expression);
                this.methodBodyHeap.Write((byte)0x7a);
            }
            this.stackHeight--;
        }
        void VisitUnaryExpression(UnaryExpression/*!*/ unaryExpression)
        {
            switch (unaryExpression.NodeType)
            {
                case NodeType.Ldtoken:
                    this.methodBodyHeap.Write((byte)0xd0);
                    Literal lit = unaryExpression.Operand as Literal;
                    if (lit != null)
                    {
                        if (lit.Value == null) return;
                        this.methodBodyHeap.Write((int)this.GetTypeDefToken((TypeNode)lit.Value));
                    }
                    else
                    {
                        if (unaryExpression.Operand == null) return;
                        Member m = ((MemberBinding)unaryExpression.Operand).BoundMember;
                        if (m == null) return;
                        Method meth = m as Method;
                        if (meth != null)
                            this.methodBodyHeap.Write((int)this.GetMethodToken(meth));
                        else
                            this.methodBodyHeap.Write((int)this.GetFieldToken((Field)m));
                    }
                    this.IncrementStackHeight();
                    return;

                case NodeType.Ldftn:
                    this.methodBodyHeap.Write((byte)0xfe);
                    this.methodBodyHeap.Write((byte)0x06);
                    this.methodBodyHeap.Write((int)this.GetMethodToken((Method)((MemberBinding)unaryExpression.Operand).BoundMember));
                    this.IncrementStackHeight();
                    return;

                case NodeType.Sizeof:
                    this.methodBodyHeap.Write((byte)0xfe);
                    this.methodBodyHeap.Write((byte)0x1c);
                    this.methodBodyHeap.Write((int)this.GetTypeToken((TypeNode)((Literal)unaryExpression.Operand).Value));
                    this.IncrementStackHeight();
                    return;

                case NodeType.SkipCheck:
                    this.methodBodyHeap.Write((byte)0xfe);
                    this.methodBodyHeap.Write((byte)0x19);
                    switch (unaryExpression.Operand.NodeType)
                    {
                        case NodeType.Castclass:
                        case NodeType.Unbox:
                            this.methodBodyHeap.Write((byte)0x01);
                            break;
                        default:
                            Debug.Assert(false);
                            this.methodBodyHeap.Write((byte)0x00);
                            break;
                    }
                    this.VisitExpression(unaryExpression.Operand);
                    return;
            }
            this.Visit(unaryExpression.Operand);
            byte opCode = 0;
            switch (unaryExpression.NodeType)
            {
                case NodeType.Neg: opCode = 0x65; break;
                case NodeType.Not: opCode = 0x66; break;
                case NodeType.Conv_I1: opCode = 0x67; break;
                case NodeType.Conv_I2: opCode = 0x68; break;
                case NodeType.Conv_I4: opCode = 0x69; break;
                case NodeType.Conv_I8: opCode = 0x6a; break;
                case NodeType.Conv_R4: opCode = 0x6b; break;
                case NodeType.Conv_R8: opCode = 0x6c; break;
                case NodeType.Conv_U4: opCode = 0x6d; break;
                case NodeType.Conv_U8: opCode = 0x6e; break;
                case NodeType.Conv_R_Un: opCode = 0x76; break;
                case NodeType.Conv_Ovf_I1_Un: opCode = 0x82; break;
                case NodeType.Conv_Ovf_I2_Un: opCode = 0x83; break;
                case NodeType.Conv_Ovf_I4_Un: opCode = 0x84; break;
                case NodeType.Conv_Ovf_I8_Un: opCode = 0x85; break;
                case NodeType.Conv_Ovf_U1_Un: opCode = 0x86; break;
                case NodeType.Conv_Ovf_U2_Un: opCode = 0x87; break;
                case NodeType.Conv_Ovf_U4_Un: opCode = 0x88; break;
                case NodeType.Conv_Ovf_U8_Un: opCode = 0x89; break;
                case NodeType.Conv_Ovf_I_Un: opCode = 0x8a; break;
                case NodeType.Conv_Ovf_U_Un: opCode = 0x8b; break;
                case NodeType.Ldlen: opCode = 0x8e; break;
                case NodeType.Conv_Ovf_I1: opCode = 0xb3; break;
                case NodeType.Conv_Ovf_U1: opCode = 0xb4; break;
                case NodeType.Conv_Ovf_I2: opCode = 0xb5; break;
                case NodeType.Conv_Ovf_U2: opCode = 0xb6; break;
                case NodeType.Conv_Ovf_I4: opCode = 0xb7; break;
                case NodeType.Conv_Ovf_U4: opCode = 0xb8; break;
                case NodeType.Conv_Ovf_I8: opCode = 0xb9; break;
                case NodeType.Conv_Ovf_U8: opCode = 0xba; break;
                case NodeType.Ckfinite: opCode = 0xc3; break;
                case NodeType.Conv_U2: opCode = 0xd1; break;
                case NodeType.Conv_U1: opCode = 0xd2; break;
                case NodeType.Conv_I: opCode = 0xd3; break;
                case NodeType.Conv_Ovf_I: opCode = 0xd4; break;
                case NodeType.Conv_Ovf_U: opCode = 0xd5; break;
                case NodeType.Conv_U: opCode = 0xe0; break;
                case NodeType.Localloc: opCode = 0x0f; this.methodBodyHeap.Write((byte)0xfe); break;
                case NodeType.Refanytype: opCode = 0x1d; this.methodBodyHeap.Write((byte)0xfe); break;
            }
            this.methodBodyHeap.Write((byte)opCode);
        }
        static void WriteArrayShape(BinaryWriter/*!*/ target, ArrayType/*!*/ arrayType)
        {
            Ir2md.WriteCompressedInt(target, arrayType.Rank);
            int n = arrayType.Sizes == null ? 0 : arrayType.Sizes.Length;
            Ir2md.WriteCompressedInt(target, n);
            for (int i = 0; i < n; i++)
            {
                //^ assert arrayType.Sizes != null;
                Ir2md.WriteCompressedInt(target, arrayType.Sizes[i]);
            }
            n = arrayType.LowerBounds == null ? 0 : arrayType.LowerBounds.Length;
            Ir2md.WriteCompressedInt(target, n);
            for (int i = 0; i < n; i++)
            {
                //^ assert arrayType.LowerBounds != null;
                Ir2md.WriteCompressedInt(target, arrayType.LowerBounds[i]);
            }
        }
        internal static void WriteCompressedInt(BinaryWriter/*!*/ target, int val)
        {
            if (val <= 0x7f)
                target.Write((byte)val);
            else if (val < 0x3fff)
            {
                target.Write((byte)((val >> 8) | 0x80));
                target.Write((byte)(val & 0xff));
            }
            else if (val < 0x1fffffff)
            {
                target.Write((byte)((val >> 24) | 0xc0));
                target.Write((byte)((val & 0xff0000) >> 16));
                target.Write((byte)((val & 0xff00) >> 8));
                target.Write((byte)(val & 0xff));
            }
            else
                Debug.Assert(false, "index too large for compression");
        }
        TypeNode/*!*/ WriteCustomModifiers(BinaryWriter/*!*/ target, TypeNode/*!*/ type)
        {
            switch (type.NodeType)
            {
                case NodeType.RequiredModifier:
                case NodeType.OptionalModifier:
                    TypeModifier tm = (TypeModifier)type;
                    target.Write((byte)tm.typeCode);
                    this.WriteTypeDefOrRefEncoded(target, tm.Modifier);
                    return this.WriteCustomModifiers(target, tm.ModifiedType);
            }
            return type;
        }
        void WriteCustomAttributeLiteral(BinaryWriter/*!*/ writer, Literal/*!*/ literal, bool needsTag)
        {
            if (literal.Type == null) return;
            ElementType typeCode = literal.Type.typeCode;
            if (needsTag)
            {
                if (typeCode == ElementType.ValueType)
                { //Boxed enum
                    writer.Write((byte)0x55);
                    this.WriteSerializedTypeName(writer, literal.Type);
                }
                else if (typeCode == ElementType.Class)
                { //a Type value
                    writer.Write((byte)0x50);
                }
                else if (typeCode != ElementType.Object) //a primitive
                    writer.Write((byte)typeCode);
            }
            Object value = literal.Value;
            //if (value == null) return; //TODO: nope, find some other way
            switch (typeCode)
            {
                case ElementType.Boolean: writer.Write((bool)value); return;
                case ElementType.Char: writer.Write((ushort)(char)value); return;
                case ElementType.Double: writer.Write((double)value); return;
                case ElementType.Single: writer.Write((float)value); return;
                case ElementType.Int16: writer.Write((short)value); return;
                case ElementType.Int32: writer.Write((int)value); return;
                case ElementType.Int64: writer.Write((long)value); return;
                case ElementType.Int8: writer.Write((sbyte)value); return;
                case ElementType.UInt16: writer.Write((ushort)value); return;
                case ElementType.UInt32: writer.Write((uint)value); return;
                case ElementType.UInt64: writer.Write((ulong)value); return;
                case ElementType.UInt8: writer.Write((byte)value); return;
                case ElementType.String: writer.Write((string)value, false); return;
                case ElementType.ValueType: this.WriteCustomAttributeLiteral(writer, new Literal(value, ((EnumNode)literal.Type).UnderlyingType), false); return;
                case ElementType.Class: this.WriteSerializedTypeName(writer, (TypeNode)value); return;
                case ElementType.SzArray:
                    TypeNode elemType = ((ArrayType)literal.Type).ElementType;
                    if (needsTag)
                        writer.Write((byte)elemType.typeCode);
                    Array array = (Array)value;
                    int numElems = array == null ? -1 : array.Length;
                    writer.Write((int)numElems);
                    for (int i = 0; i < numElems; i++)
                        this.WriteCustomAttributeLiteral(writer, new Literal(array.GetValue(i), elemType), false);
                    return;
                case ElementType.Object:
                    Literal lit = (Literal)literal.Clone();
                    TypeNode t = null;
                    switch (Convert.GetTypeCode(lit.Value))
                    {
                        case TypeCode.Boolean: t = CoreSystemTypes.Boolean; break;
                        case TypeCode.Byte: t = CoreSystemTypes.UInt8; break;
                        case TypeCode.Char: t = CoreSystemTypes.Char; break;
                        case TypeCode.Double: t = CoreSystemTypes.Double; break;
                        case TypeCode.Int16: t = CoreSystemTypes.Int16; break;
                        case TypeCode.Int32: t = CoreSystemTypes.Int32; break;
                        case TypeCode.Int64: t = CoreSystemTypes.Int64; break;
                        case TypeCode.SByte: t = CoreSystemTypes.Int8; break;
                        case TypeCode.Single: t = CoreSystemTypes.Single; break;
                        case TypeCode.String: t = CoreSystemTypes.String; break;
                        case TypeCode.UInt16: t = CoreSystemTypes.UInt16; break;
                        case TypeCode.UInt32: t = CoreSystemTypes.UInt32; break;
                        case TypeCode.UInt64: t = CoreSystemTypes.UInt64; break;
                        case TypeCode.Empty:
                        case TypeCode.Object:
                            Array arr = lit.Value as Array;
                            if (arr != null)
                            {
#if !NoReflection
                                t = TypeNode.GetTypeNode(arr.GetType());
#else
                System.Type reflType = arr.GetType();
                System.Type reflElemType = reflType.GetElementType();
                AssemblyNode assem = AssemblyNode.GetAssembly(reflType.Assembly.Location);
                TypeNode cciElemType = assem.GetType(Identifier.For(reflElemType.Namespace), Identifier.For(reflElemType.Name));
                t = cciElemType.GetArrayType(reflType.GetArrayRank());
#endif
                            }
                            else
                                t = CoreSystemTypes.Type;
                            break;
                    }
                    if (t == null) break;
                    lit.Type = t;
                    this.WriteCustomAttributeLiteral(writer, lit, true);
                    return;
            }
            Debug.Assert(false, "Unexpected type in custom attribute");
        }
        bool AttributesContains(AttributeList al, TypeNode/*!*/ a)
        {
            if (al == null) return false;
            for (int i = 0, n = al.Count; i < n; i++)
            {
                if (al[i] != null && al[i].Type == a)
                    return true;
            }
            return false;
        }
        void WriteMethodSignature(BinaryWriter/*!*/ target, Method/*!*/ method)
        {
            if (this.UseGenerics)
            {
                if (method.Template != null && method.Template.IsGeneric)
                {
                    //Signature is being used in MethodDef table
                    TypeNodeList types = method.TemplateArguments;
                    int m = types == null ? 0 : types.Count;
                    target.Write((byte)(method.CallingConvention | CallingConventionFlags.Generic));
                    Ir2md.WriteCompressedInt(target, m);
                }
                else if (method.DeclaringType.Template != null && method.DeclaringType.Template.IsGeneric)
                {
                    Method unspecializedMethod = this.GetUnspecializedMethod(method);
                    this.WriteMethodSignature(target, unspecializedMethod);
                    return;
                }
                else if (method.IsGeneric)
                {
                    TypeNodeList types = method.TemplateParameters;
                    int m = types == null ? 0 : types.Count;
                    target.Write((byte)(method.CallingConvention | CallingConventionFlags.Generic));
                    Ir2md.WriteCompressedInt(target, m);
                }
                else
                    target.Write((byte)method.CallingConvention);
            }
            else
                target.Write((byte)method.CallingConvention);
            ParameterList pars = method.Parameters;
            int n = pars == null ? 0 : pars.Count;
            Ir2md.WriteCompressedInt(target, n);

            TypeNode returnType = method.ReturnType;
#if ExtendedRuntime
      if (method.HasOutOfBandContract || this.AttributesContains(method.ReturnAttributes, SystemTypes.NotNullAttribute)) {
        returnType = TypeNode.DeepStripModifiers(returnType, (method.Template != null) ? method.Template.ReturnType : null, SystemTypes.NonNullType, SystemTypes.NullableType);
    //    returnType = TypeNode.DeepStripModifier(returnType, SystemTypes.NullableType, (method.Template != null) ? returnType.GetTemplateInstance(returnType, returnType.TemplateArguments) : null);
      }
#endif
            if (returnType == null) returnType = SystemTypes.Object;
            this.WriteTypeSignature(target, returnType, true);
            for (int i = 0; i < n; i++)
            {
                Parameter p = pars[i];
                if (p == null) continue;
                TypeNode parameterType = p.Type;
#if ExtendedRuntime
        if (method.HasOutOfBandContract || this.AttributesContains(p.Attributes, SystemTypes.NotNullAttribute)) {
          parameterType = TypeNode.DeepStripModifiers(parameterType, (method.Template != null) ? method.Template.Parameters[i].Type : null, SystemTypes.NonNullType, SystemTypes.NullableType);
          //parameterType = TypeNode.DeepStripModifier(parameterType, SystemTypes.NullableType, (method.Template != null) ? parameterType.GetTemplateInstance(parameterType, parameterType.TemplateArguments) : null);
        }
#endif
                if (parameterType == null) parameterType = SystemTypes.Object;
                this.WriteTypeSignature(target, parameterType);
            }
        }
        void WriteMethodSpecSignature(BinaryWriter/*!*/ target, Method/*!*/ method)
        //^ requires this.UseGenerics && method.Template != null && method.Template.IsGeneric;
        {
            Debug.Assert(this.UseGenerics && method.Template != null && method.Template.IsGeneric);
            target.Write((byte)0x0a);
            TypeNodeList types = method.TemplateArguments;
            int m = types == null ? 0 : types.Count;
            Ir2md.WriteCompressedInt(target, m);
            for (int i = 0; i < m; i++)
            {
                //^ assert types != null;
                this.WriteTypeSignature(target, types[i]);
            }
        }
        void WriteMethodSignature(BinaryWriter/*!*/ target, FunctionPointer/*!*/ fp)
        {
            target.Write((byte)fp.CallingConvention);
            TypeNodeList parTypes = fp.ParameterTypes;
            int n = parTypes == null ? 0 : parTypes.Count;
            Ir2md.WriteCompressedInt(target, n);
            if (fp.ReturnType != null)
                this.WriteTypeSignature(target, fp.ReturnType);
            int m = fp.VarArgStart;
            for (int i = 0; i < n; i++)
            {
                //^ assert parTypes != null;
                if (i == m) target.Write((byte)0x41); //Sentinel
                this.WriteTypeSignature(target, parTypes[i]);
            }
        }
        void WritePropertySignature(BinaryWriter/*!*/ target, Property/*!*/ prop)
        {
            byte propHeader = (byte)0x8;
            if (!prop.IsStatic) propHeader |= (byte)0x20; //bizarre redundant way to indicate that property accessors are instance methods
            target.Write(propHeader);
            ParameterList pars = prop.Parameters;
            int n = pars == null ? 0 : pars.Count;
            Ir2md.WriteCompressedInt(target, n);
            if (prop.Type != null) this.WriteTypeSignature(target, prop.Type);
            for (int i = 0; i < n; i++)
            {
                //^ assert pars != null;
                Parameter par = pars[i];
                if (par == null || par.Type == null) continue;
                this.WriteTypeSignature(target, par.Type);
            }
        }
        void WriteSerializedTypeName(BinaryWriter target, TypeNode type)
        {
            if (target == null || type == null) return;
            target.Write(this.GetSerializedTypeName(type), false);
        }
        string GetSerializedTypeName(TypeNode/*!*/ type)
        {
            bool isAssemblyQualified = true;
            return this.GetSerializedTypeName(type, ref isAssemblyQualified);
        }
        string GetSerializedTypeName(TypeNode/*!*/ type, ref bool isAssemblyQualified)
        {
            if (type == null) return null;
            this.VisitReferencedType(type);
            StringBuilder sb = new StringBuilder();
            TypeModifier tMod = type as TypeModifier;
            if (tMod != null)
            {
                sb.Append(this.GetTypeDefOrRefOrSpecEncoded(type));
                sb.Append('!');
                return sb.ToString();
            }
            ArrayType arrType = type as ArrayType;
            if (arrType != null)
            {
                type = arrType.ElementType;
                bool isAssemQual = false;
                this.AppendSerializedTypeName(sb, arrType.ElementType, ref isAssemQual);
                if (arrType.IsSzArray())
                    sb.Append("[]");
                else
                {
                    sb.Append('[');
                    if (arrType.Rank == 1) sb.Append('*');
                    for (int i = 1; i < arrType.Rank; i++) sb.Append(',');
                    sb.Append(']');
                }
                goto done;
            }
            Pointer pointer = type as Pointer;
            if (pointer != null)
            {
                type = pointer.ElementType;
                bool isAssemQual = false;
                this.AppendSerializedTypeName(sb, pointer.ElementType, ref isAssemQual);
                sb.Append('*');
                goto done;
            }
            Reference reference = type as Reference;
            if (reference != null)
            {
                type = reference.ElementType;
                bool isAssemQual = false;
                this.AppendSerializedTypeName(sb, reference.ElementType, ref isAssemQual);
                sb.Append('&');
                goto done;
            }
            if (type.Template == null)
                sb.Append(type.FullName);
            else
            {
                sb.Append(type.Template.FullName);
                sb.Append('[');
                for (int i = 0, n = type.TemplateArguments == null ? 0 : type.TemplateArguments.Count; i < n; i++)
                {
                    //^ assert type.TemplateArguments != null;
                    bool isAssemQual = true;
                    this.AppendSerializedTypeName(sb, type.TemplateArguments[i], ref isAssemQual);
                    if (i < n - 1) sb.Append(',');
                }
                sb.Append(']');
            }
        done:
            if (isAssemblyQualified)
                this.AppendAssemblyQualifierIfNecessary(sb, type, out isAssemblyQualified);
            return sb.ToString();
        }
        void AppendAssemblyQualifierIfNecessary(StringBuilder/*!*/ sb, TypeNode type, out bool isAssemQualified)
        {
            isAssemQualified = false;
            if (type == null) return;
            AssemblyNode referencedAssembly = type.DeclaringModule as AssemblyNode;
            if (referencedAssembly != null && referencedAssembly != this.module /*&& referencedAssembly != CoreSystemTypes.SystemAssembly*/)
            {
                sb.Append(", ");
                sb.Append(referencedAssembly.StrongName);
                isAssemQualified = true;
            }
        }
        void AppendSerializedTypeName(StringBuilder/*!*/ sb, TypeNode type, ref bool isAssemQualified)
        {
            if (type == null) return;
            string argTypeName = this.GetSerializedTypeName(type, ref isAssemQualified);
            if (isAssemQualified) sb.Append('[');
            sb.Append(argTypeName);
            if (isAssemQualified) sb.Append(']');
        }
        void WriteTypeDefOrRefEncoded(BinaryWriter/*!*/ target, TypeNode/*!*/ type)
        {
            if (!type.IsGeneric && this.IsStructural(type) && !(type is ITypeParameter))
                this.WriteTypeSpecEncoded(target, type);
            else if (type.DeclaringModule == this.module)
                this.WriteTypeDefEncoded(target, type);
            else if (type.DeclaringModule != null)
                this.WriteTypeRefEncoded(target, type);
            else
                Debug.Assert(false);
        }
        void WriteTypeDefEncoded(BinaryWriter/*!*/ target, TypeNode/*!*/ type)
        {
            int tok = this.GetTypeDefIndex(type);
            Ir2md.WriteCompressedInt(target, (tok << 2));
        }
        void WriteTypeRefEncoded(BinaryWriter/*!*/ target, TypeNode/*!*/ type)
        {
            int tok = this.GetTypeRefIndex(type);
            Ir2md.WriteCompressedInt(target, (tok << 2) | 1);
        }
        void WriteTypeSpecEncoded(BinaryWriter/*!*/ target, TypeNode/*!*/ type)
        {
            int tok = this.GetTypeSpecIndex(type);
            Ir2md.WriteCompressedInt(target, (tok << 2) | 2);
        }
        void WriteTypeSignature(BinaryWriter/*!*/ target, TypeNode/*!*/ type)
        {
            this.WriteTypeSignature(target, type, false);
        }
        void WriteTypeSignature(BinaryWriter/*!*/ target, TypeNode/*!*/ type, bool instantiateGenericTypes)
        {
            if (type == null) return;
            TypeNode t = this.WriteCustomModifiers(target, type);
            if (this.UseGenerics)
            {
                if (t.Template != null && t.Template.IsGeneric && t.TemplateParameters == null)
                {
                    target.Write((byte)0x15);
                    TypeNode template = t.Template;
                    while (template.Template != null) template = template.Template;
                    this.WriteTypeSignature(target, template);
                    TypeNodeList templArgs = t.ConsolidatedTemplateArguments;
                    int n = templArgs == null ? 0 : templArgs.Count;
                    Ir2md.WriteCompressedInt(target, n);
                    for (int i = 0; i < n; i++)
                    {
                        //^ assume templArgs != null;
                        TypeNode targ = templArgs[i];
                        if (targ == null) continue;
                        this.WriteTypeSignature(target, targ);
                    }
                    return;
                }
                else if (t.IsGeneric && instantiateGenericTypes)
                {
                    while (t.Template != null) t = t.Template;
                    target.Write((byte)0x15);
                    this.WriteTypeSignature(target, t);
                    TypeNodeList templPars = t.ConsolidatedTemplateParameters;
                    int n = templPars == null ? 0 : templPars.Count;
                    Ir2md.WriteCompressedInt(target, n);
                    for (int i = 0; i < n; i++)
                    {
                        //^ assume templPars != null;
                        TypeNode tp = templPars[i];
                        if (tp == null) continue;
                        this.WriteTypeSignature(target, tp);
                    }
                    return;
                }
                if (t is ITypeParameter)
                {
                    object num = this.typeParameterNumber[t.UniqueKey];
                    if (num is int)
                    {
                        int number = (int)num;
                        if (number < 0)
                        {
                            target.Write((byte)0x1e); number = -number;
                        }
                        else
                            target.Write((byte)0x13);
                        Ir2md.WriteCompressedInt(target, number - 1);
                        return;
                    }
                }
            }
            target.Write((byte)t.typeCode);
            switch (t.typeCode)
            {
                case ElementType.Pointer: this.WriteTypeSignature(target, ((Pointer)t).ElementType); break;
                case ElementType.Reference: this.WriteTypeSignature(target, ((Reference)t).ElementType); break;
                case ElementType.ValueType:
                case ElementType.Class: this.WriteTypeDefOrRefEncoded(target, t); break;
                case ElementType.Array: this.WriteTypeSignature(target, ((ArrayType)t).ElementType); Ir2md.WriteArrayShape(target, (ArrayType)t); break;
                case ElementType.FunctionPointer: this.WriteMethodSignature(target, (FunctionPointer)t); break;
                case ElementType.SzArray: this.WriteTypeSignature(target, ((ArrayType)t).ElementType); break;
            }
        }

#if !ROTOR
        void IMetaDataEmit.SetModuleProps(string szName)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.Save(string szFile, uint dwSaveFlags)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SaveToStream(void* pIStream, uint dwSaveFlags)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataEmit.GetSaveSize(uint fSave)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineTypeDef(char* szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint* rtkImplements)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineNestedType(char* szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint* rtkImplements, uint tdEncloser)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetHandler([MarshalAs(UnmanagedType.IUnknown), In]object pUnk)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineMethod(uint td, char* zName, uint dwMethodFlags, byte* pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.DefineMethodImpl(uint td, uint tkBody, uint tkDecl)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineTypeRefByName(uint tkResolutionScope, char* szName)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineImportType(IntPtr pAssemImport, void* pbHashValue, uint cbHashValue, IMetaDataImport pImport,
          uint tdImport, IntPtr pAssemEmit)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineMemberRef(uint tkImport, string szName, byte* pvSigBlob, uint cbSigBlob)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineImportMember(IntPtr pAssemImport, void* pbHashValue, uint cbHashValue,
          IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineEvent(uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint* rmdOtherMethods)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetClassLayout(uint td, uint dwPackSize, COR_FIELD_OFFSET* rFieldOffsets, uint ulClassSize)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.DeleteClassLayout(uint td)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetFieldMarshal(uint tk, byte* pvNativeType, uint cbNativeType)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.DeleteFieldMarshal(uint tk)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefinePermissionSet(uint tk, uint dwAction, void* pvPermission, uint cbPermission)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetRVA(uint md, uint ulRVA)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.GetTokenFromSig(byte* pvSig, uint cbSig)
        {
            BinaryWriter sig = new BinaryWriter(new MemoryStream());
            for (int i = 0; i < cbSig; i++) sig.Write(*(pvSig + i));
            return (uint)(0x11000000 | this.GetStandAloneSignatureIndex(sig));
        }
        uint IMetaDataEmit.DefineModuleRef(string szName)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetParent(uint mr, uint tk)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.GetTokenFromTypeSpec(byte* pvSig, uint cbSig)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SaveToMemory(void* pbData, uint cbData)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataEmit.DefineUserString(string szString, uint cchString)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.DeleteToken(uint tkObj)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetMethodProps(uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetTypeDefProps(uint td, uint dwTypeDefFlags, uint tkExtends, uint* rtkImplements)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetEventProps(uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint* rmdOtherMethods)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.SetPermissionSetProps(uint tk, uint dwAction, void* pvPermission, uint cbPermission)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.DefinePinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetPinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.DeletePinvokeMap(uint tk)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineCustomAttribute(uint tkObj, uint tkType, void* pCustomAttribute, uint cbCustomAttribute)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetCustomAttributeValue(uint pcv, void* pCustomAttribute, uint cbCustomAttribute)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineField(uint td, string szName, uint dwFieldFlags, byte* pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag,
          void* pValue, uint cchValue)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineProperty(uint td, string szProperty, uint dwPropFlags, byte* pvSig, uint cbSig, uint dwCPlusTypeFlag,
          void* pValue, uint cchValue, uint mdSetter, uint mdGetter, uint* rmdOtherMethods)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.DefineParam(uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetFieldProps(uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetPropertyProps(uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue, uint mdSetter, uint mdGetter, uint* rmdOtherMethods)
        {
            throw new NotImplementedException();
        }
        unsafe void IMetaDataEmit.SetParamProps(uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, void* pValue, uint cchValue)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataEmit.DefineSecurityAttributeSet(uint tkObj, IntPtr rSecAttrs, uint cSecAttrs)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.ApplyEditAndContinue([MarshalAs(UnmanagedType.IUnknown)]object pImport)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataEmit.TranslateSigWithScope(IntPtr pAssemImport, void* pbHashValue, uint cbHashValue,
          IMetaDataImport import, byte* pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, byte* pvTranslatedSig, uint cbTranslatedSigMax)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetMethodImplFlags(uint md, uint dwImplFlags)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.SetFieldRVA(uint fd, uint ulRVA)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.Merge(IMetaDataImport pImport, IntPtr pHostMapToken, [MarshalAs(UnmanagedType.IUnknown)]object pHandler)
        {
            throw new NotImplementedException();
        }
        void IMetaDataEmit.MergeEnd()
        {
            throw new NotImplementedException();
        }
        [PreserveSig]
        void IMetaDataImport.CloseEnum(uint hEnum)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.CountEnum(uint hEnum)
        {
            throw new NotImplementedException();
        }
        void IMetaDataImport.ResetEnum(uint hEnum, uint ulPos)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumTypeDefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeDefs, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumInterfaceImpls(ref uint phEnum, uint td, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rImpls, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumTypeRefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeRefs, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.FindTypeDefByName(string szTypeDef, uint tkEnclosingClass)
        {
            throw new NotImplementedException();
        }
        Guid IMetaDataImport.GetScopeProps(StringBuilder szName, uint cchName, out uint pchName)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetModuleFromScope()
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetTypeDefProps(uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags)
        {
            pchTypeDef = 0;
            if (td == 0) return 0;
            TypeNode t = null;
            if ((td & 0xFF000000) == 0x1B000000)
            {
                t = this.typeSpecEntries[(int)(td & 0xFFFFFF) - 1];
                if (t.Template != null) t = t.Template;
            }
            else
                t = this.typeDefEntries[(int)(td & 0xFFFFFF) - 1];
            if (t == null || t.Name == null) return 0;
            string tName = t.Name.ToString();
            if (tName == null) return 0;
            pchTypeDef = (uint)tName.Length;
            if (pchTypeDef >= cchTypeDef) pchTypeDef = cchTypeDef - 1;
            char* pTypeDef = (char*)szTypeDef.ToPointer();
            for (int i = 0; i < pchTypeDef; i++) *(pTypeDef + i) = tName[i];
            *(pTypeDef + pchTypeDef) = (char)0;
            uint* pFlags = (uint*)pdwTypeDefFlags.ToPointer();
            *(pFlags) = (uint)t.Flags;
            TypeNode bt = t.BaseType;
            if (bt == null) return 0;
            return (uint)this.GetTypeToken(bt);
        }
        uint IMetaDataImport.GetInterfaceImplProps(uint iiImpl, out uint pClass)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetTypeRefProps(uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.ResolveTypeRef(uint tr, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppIScope)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumMembers(ref uint phEnum, uint cl, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rMembers, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumMembersWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMembers, uint cMax)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.EnumMethods(ref uint phEnum, uint cl, uint* rMethods, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumMethodsWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethods, uint cMax)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.EnumFields(ref uint phEnum, uint cl, uint* rFields, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumFieldsWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rFields, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumParams(ref uint phEnum, uint mb, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rParams, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumMemberRefs(ref uint phEnum, uint tkParent, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rMemberRefs, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumMethodImpls(ref uint phEnum, uint td, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethodBody,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethodDecl, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumPermissionSets(ref uint phEnum, uint tk, uint dwActions, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rPermission,
          uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.FindMember(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.FindMethod(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.FindField(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.FindMemberRef(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetMethodProps(uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr,
          IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA)
        {
            Method m = null;
            if ((mb & 0xFF000000) == 0x0A000000)
                m = this.memberRefEntries[(int)(mb & 0xFFFFFF) - 1] as Method;
            else
                m = this.methodEntries[(int)(mb & 0xFFFFFF) - 1];
            pchMethod = 0;
            pClass = 0;
            if (m == null || m.DeclaringType == null) return 0;
            pClass = (uint)this.GetTypeDefToken(m.DeclaringType);
            string methName = m.Name == null ? null : m.Name.ToString();
            if (methName == null) return 0;
            pchMethod = (uint)methName.Length;
            char* pMethName = (char*)szMethod.ToPointer();
            for (int i = 0; i < pchMethod; i++) *(pMethName + i) = methName[i];
            *(pMethName + pchMethod) = (char)0;
            return 0;
        }
        unsafe uint IMetaDataImport.GetMemberRefProps(uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out byte* ppvSigBlob)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.EnumProperties(ref uint phEnum, uint td, uint* rProperties, uint cMax)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.EnumEvents(ref uint phEnum, uint td, uint* rEvents, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetEventProps(uint ev, out uint pClass, StringBuilder szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags,
          out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire,
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 11)] uint[] rmdOtherMethod, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumMethodSemantics(ref uint phEnum, uint mb, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rEventProp, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetMethodSemantics(uint mb, uint tkEventProp)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetClassLayout(uint td, out uint pdwPackSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] COR_FIELD_OFFSET[] rFieldOffset, uint cMax, out uint pcFieldOffset)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetFieldMarshal(uint tk, out byte* ppvNativeType)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetRVA(uint tk, out uint pulCodeRVA)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetPermissionSetProps(uint pm, out uint pdwAction, out void* ppvPermission)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetSigFromToken(uint mdSig, out byte* ppvSig)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetModuleRefProps(uint mur, StringBuilder szName, uint cchName)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumModuleRefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rModuleRefs, uint cmax)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetTypeSpecFromToken(uint typespec, out byte* ppvSig)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetNameFromToken(uint tk)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumUnresolvedMethods(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rMethods, uint cMax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetUserString(uint stk, StringBuilder szString, uint cchString)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetPinvokeMap(uint tk, out uint pdwMappingFlags, StringBuilder szImportName, uint cchImportName, out uint pchImportName)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumSignatures(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rSignatures, uint cmax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumTypeSpecs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeSpecs, uint cmax)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumUserStrings(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rStrings, uint cmax)
        {
            throw new NotImplementedException();
        }
        [PreserveSig]
        int IMetaDataImport.GetParamForMethodIndex(uint md, uint ulParamSeq, out uint pParam)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.EnumCustomAttributes(ref uint phEnum, uint tk, uint tkType, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rCustomAttributes, uint cMax)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetCustomAttributeProps(uint cv, out uint ptkObj, out uint ptkType, out void* ppBlob)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.FindTypeRef(uint tkResolutionScope, string szName)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetMemberProps(uint mb, out uint pClass, StringBuilder szMember, uint cchMember, out uint pchMember, out uint pdwAttr,
          out byte* ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out void* ppValue)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetFieldProps(uint mb, out uint pClass, StringBuilder szField, uint cchField, out uint pchField, out uint pdwAttr,
          out byte* ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out void* ppValue)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetPropertyProps(uint prop, out uint pClass, StringBuilder szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags,
          out byte* ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out void* ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter,
          out uint pmdGetter, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 14)] uint[] rmdOtherMethod, uint cMax)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetParamProps(uint tk, out uint pmd, out uint pulSequence, StringBuilder szName, uint cchName, out uint pchName,
          out uint pdwAttr, out uint pdwCPlusTypeFlag, out void* ppValue)
        {
            throw new NotImplementedException();
        }
        unsafe uint IMetaDataImport.GetCustomAttributeByName(uint tkObj, string szName, out void* ppData)
        {
            throw new NotImplementedException();
        }
        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Bool)]
        bool IMetaDataImport.IsValidToken(uint tk)
        {
            throw new NotImplementedException();
        }
        uint IMetaDataImport.GetNestedClassProps(uint tdNestedClass)
        {
            TypeNode t = null;
            if ((tdNestedClass & 0xFF000000) == 0x1B000000)
                t = this.typeSpecEntries[(int)(tdNestedClass & 0xFFFFFF) - 1];
            else
                t = this.typeDefEntries[(int)(tdNestedClass & 0xFFFFFF) - 1];
            if (t == null || t.DeclaringType == null) return 0;
            return (uint)this.GetTypeToken(t.DeclaringType);
        }
        unsafe uint IMetaDataImport.GetNativeCallConvFromSig(void* pvSig, uint cbSig)
        {
            throw new NotImplementedException();
        }
        int IMetaDataImport.IsGlobal(uint pd)
        {
            throw new NotImplementedException();
        }
#endif
    }
#if WHIDBEYwithGenericsAndIEqualityComparer
    public class ByteArrayKeyComparer : IEqualityComparer, IComparer
    {
        int IComparer.Compare(object x, object y)
        {
            if (x == null || y == null) throw new ArgumentNullException();
            byte[] xa = (byte[])x;
            byte[] ya = (byte[])y;
            int n = xa.Length;
            int result = n - ya.Length;
            if (result != 0) return result;
            for (int i = 0; i < n; i++)
            {
                result = xa[i] - ya[i];
                if (result != 0) return result;
            }
            return 0;
        }
        bool IEqualityComparer.Equals(object x, object y)
        {
            if (x == null || y == null) return x == y;
            return ((IComparer)this).Compare(x, y) == 0;
        }
        int IEqualityComparer.GetHashCode(object/*!*/ x)
        {
            Debug.Assert(x != null);
            byte[] xa = (byte[])x;
            int hcode = 1;
            for (int i = 0, n = xa.Length; i < n; i++)
                hcode = hcode * 17 + xa[i];
            return hcode;
        }
    }
#elif WHIDBEYwithGenerics
  public class ByteArrayKeyComparer : IKeyComparer{
    int IComparer.Compare(object x, object y) {
      if (x == null || y == null) throw new ArgumentNullException();
      byte[] xa = (byte[])x;
      byte[] ya = (byte[])y;
      int n = xa.Length;
      int result = n - ya.Length;
      if (result != 0) return result;
      for (int i = 0; i < n; i++){
        result = xa[i] - ya[i];
        if (result != 0) return result;
      }
      return 0;
    }
    bool IKeyComparer.Equals(object x, object y){
      return ((IKeyComparer)this).Compare(x, y) == 0;
    }
    int IHashCodeProvider.GetHashCode(object x) {
      Debug.Assert(x != null);
      byte[] xa = (byte[])x;
      int hcode = 1;
      for (int i = 0, n = xa.Length; i < n; i++)
        hcode = hcode * 17 + xa[i];
      return hcode;
    }
  }
#else
  public class ByteArrayComparer : IComparer{
    int IComparer.Compare(object x, object y){
      if (x == null || y == null) throw new ArgumentNullException();
      byte[] xa = (byte[])x;
      byte[] ya = (byte[])y;
      int n = xa.Length;
      int result = n - ya.Length;
      if (result != 0) return result;
      for (int i = 0; i < n; i++){
        result = xa[i] - ya[i];
        if (result != 0) return result;
      }
      return 0;
    }
  }
  public class ByteArrayHasher : IHashCodeProvider{
    int IHashCodeProvider.GetHashCode(object x){
      Debug.Assert(x != null);
      byte[] xa = (byte[])x;
      int hcode = 1;
      for (int i = 0, n = xa.Length; i < n; i++)
        hcode = hcode*17 + xa[i];
      return hcode;
    }
  }
#endif
    internal class Fixup
    {
        internal int fixupLocation;
        internal int addressOfNextInstruction;
        internal bool shortOffset;
        internal Fixup nextFixUp;
    }
    internal class MethodInfo
    {
        internal TrivialHashtable/*!*/ fixupIndex = new TrivialHashtable();
        internal int localVarSigTok;
        internal BinaryWriter/*!*/ localVarSignature;
        internal TrivialHashtable/*!*/ localVarIndex;
#if !ROTOR
        internal NodeList/*!*/ statementNodes;
        internal LocalList/*!*/ debugLocals;
        internal Int32List/*!*/ signatureLengths;
        internal Int32List/*!*/ signatureOffsets;
        internal Int32List/*!*/ statementOffsets;
#endif

        public MethodInfo()
        {
            //^ base();
        }
    }
    public class KeyFileNotFoundException : System.ArgumentException { }
    public class AssemblyCouldNotBeSignedException : System.ApplicationException { }
    public class DebugSymbolsCouldNotBeWrittenException : System.ApplicationException { }
    internal class Writer
    {
        private Writer() { }
        internal static void WritePE(System.CodeDom.Compiler.CompilerParameters/*!*/ compilerParameters, Module/*!*/ module)
        //^ requires module.Location != null;
        {
            if (compilerParameters == null) { Debug.Assert(false); return; }
            CompilerOptions options = compilerParameters as CompilerOptions;
            if (options == null)
                Writer.WritePE(module.Location, compilerParameters.IncludeDebugInformation, module, false, null, null);
            else
            {
                if (options.FileAlignment > 512) module.FileAlignment = options.FileAlignment;
                Writer.WritePE(module.Location, options.IncludeDebugInformation, module, options.DelaySign, options.AssemblyKeyFile, options.AssemblyKeyName);
            }
        }
        internal static void WritePE(string/*!*/ location, bool writeDebugSymbols, Module/*!*/ module)
        {
            Writer.WritePE(location, writeDebugSymbols, module, false, null, null);
        }
        private static void WritePE(string/*!*/ location, bool writeDebugSymbols, Module/*!*/ module, bool delaySign, string keyFileName, string keyName)
        {
            AssemblyNode assem = module as AssemblyNode;
            location = Path.GetFullPath(location);
            module.Directory = Path.GetDirectoryName(location);
            bool keyFileNameDoesNotExist = false;
            if (assem != null)
            {
                assem.KeyContainerName = keyName;
                if (keyFileName != null && keyFileName.Length > 0)
                {
                    if (!File.Exists(keyFileName)) keyFileName = Path.Combine(module.Directory, keyFileName);
                    if (File.Exists(keyFileName))
                    {
                        using (FileStream keyFile = File.OpenRead(keyFileName))
                        {
                            long size = keyFile.Length;
                            if (size > int.MaxValue) throw new System.IO.FileLoadException();
                            int n = (int)size;
                            byte[] key = new byte[n];
                            keyFile.Read(key, 0, n);
                            assem.KeyBlob = key;
                        }
                    }
                    else
                        keyFileNameDoesNotExist = true;
                }
                assem.PublicKeyOrToken = Writer.GetPublicKey(assem);
            }
            using (FileStream exeFstream = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                string debugSymbolsLocation = writeDebugSymbols ? Path.ChangeExtension(location, "pdb") : null;
                if (debugSymbolsLocation != null && File.Exists(debugSymbolsLocation))
                    File.Delete(debugSymbolsLocation);
                MemoryStream exeMstream = new MemoryStream();
                Ir2md.WritePE(module, debugSymbolsLocation, new BinaryWriter(exeMstream));
                exeMstream.WriteTo(exeFstream);
            }
            if (keyFileNameDoesNotExist) throw new KeyFileNotFoundException();
            if (delaySign || assem == null) return;
            if (assem.KeyBlob != null || (assem.KeyContainerName != null && assem.KeyContainerName.Length > 0))
            {
                try
                {
                    if (!Writer.StrongNameSignatureGeneration(location, keyName, assem.KeyBlob, assem.KeyBlob == null ? 0 : assem.KeyBlob.Length, IntPtr.Zero, IntPtr.Zero))
                        throw new AssemblyCouldNotBeSignedException();
                }
                catch
                {
                    if (!Writer.MscorsnStrongNameSignatureGeneration(location, keyName, assem.KeyBlob, assem.KeyBlob == null ? 0 : assem.KeyBlob.Length, IntPtr.Zero, IntPtr.Zero))
                        throw new AssemblyCouldNotBeSignedException();
                }
            }
        }
        [DllImport("mscoree.dll", EntryPoint = "StrongNameSignatureGeneration",
           SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
           CallingConvention = CallingConvention.StdCall)]
        private static extern bool StrongNameSignatureGeneration(
          string wszFilePath,        // [in] valid path to the PE file for the assembly
          string wszKeyContainer,    // [in] desired key container name
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)]
      byte[] pbKeyBlob,          // [in] public/private key blob (optional)
          int cbKeyBlob,
          IntPtr ppbSignatureBlob,   // [out] signature blob
          IntPtr pcbSignatureBlob);
        [DllImport("mscorsn.dll", EntryPoint = "StrongNameSignatureGeneration",
           SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
           CallingConvention = CallingConvention.StdCall)]
        private static extern bool MscorsnStrongNameSignatureGeneration(
          string wszFilePath,        // [in] valid path to the PE file for the assembly
          string wszKeyContainer,    // [in] desired key container name
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)]
      byte[] pbKeyBlob,          // [in] public/private key blob (optional)
          int cbKeyBlob,
          IntPtr ppbSignatureBlob,   // [out] signature blob
          IntPtr pcbSignatureBlob);
        private unsafe static byte[] GetPublicKey(AssemblyNode/*!*/ assem)
        {
            Debug.Assert(assem != null);
            IntPtr publicKey = IntPtr.Zero;
            int size;
            try
            {
                if (assem.KeyBlob != null)
                {
                    Writer.StrongNameGetPublicKey(null, assem.KeyBlob, assem.KeyBlob.Length, out publicKey, out size);
                    if (publicKey == IntPtr.Zero) return assem.KeyBlob;
                }
                else if (assem.KeyContainerName != null)
                {
                    Writer.StrongNameGetPublicKey(assem.KeyContainerName, null, 0, out publicKey, out size);
                    if (publicKey == IntPtr.Zero) return null;
                }
                else
                    return assem.PublicKeyOrToken;
                byte[] result = new byte[size];
                byte* ptr = (byte*)publicKey;
                for (int i = 0; i < size; i++) result[i] = *ptr++;
                return result;
            }
            catch { }
            {
                if (assem.KeyBlob != null)
                {
                    Writer.MscorsnStrongNameGetPublicKeyUsing(null, assem.KeyBlob, assem.KeyBlob.Length, out publicKey, out size);
                    if (publicKey == IntPtr.Zero) return assem.KeyBlob;
                }
                else if (assem.KeyContainerName != null)
                {
                    Writer.MscorsnStrongNameGetPublicKeyUsing(assem.KeyContainerName, null, 0, out publicKey, out size);
                    if (publicKey == IntPtr.Zero) return null;
                }
                else
                    return assem.PublicKeyOrToken;
                byte[] result = new byte[size];
                byte* ptr = (byte*)publicKey;
                for (int i = 0; i < size; i++) result[i] = *ptr++;
                return result;
            }
        }
        [DllImport("mscoree.dll", EntryPoint = "StrongNameGetPublicKey",
           SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
           CallingConvention = CallingConvention.StdCall)]
        private static extern bool StrongNameGetPublicKey(
          string wszKeyContainer,    // [in] desired key container name
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
      byte[] pbKeyBlob,          // [in] public/private key blob (optional)
          int cbKeyBlob,
          [Out] out IntPtr ppbPublicKeyBlob,   // [out] public key blob
          [Out] out int pcbPublicKeyBlob);
        [DllImport("mscorsn.dll", EntryPoint = "StrongNameGetPublicKey",
           SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
           CallingConvention = CallingConvention.StdCall)]
        private static extern bool MscorsnStrongNameGetPublicKeyUsing(
          string wszKeyContainer,    // [in] desired key container name
          [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
      byte[] pbKeyBlob,          // [in] public/private key blob (optional)
          int cbKeyBlob,
          [Out] out IntPtr ppbPublicKeyBlob,   // [out] public key blob
          [Out] out int pcbPublicKeyBlob);

        internal static void WritePE(Stream/*!*/ executable, Stream debugSymbols, Module/*!*/ module)
        {
            MemoryStream mstream = new MemoryStream();
            Ir2md.WritePE(module, null, new BinaryWriter(mstream)); //TODO: need to write the PDB symbols to the stream
            mstream.WriteTo(executable);
        }
        internal static void WritePE(out byte[] executable, Module/*!*/ module)
        {
            MemoryStream mstream = new MemoryStream();
            Ir2md.WritePE(module, null, new BinaryWriter(mstream));
            executable = mstream.ToArray();
        }
        internal static void WritePE(out byte[] executable, out byte[] debugSymbols, Module/*!*/ module)
        {
            MemoryStream mstream = new MemoryStream();
            Ir2md.WritePE(module, null, new BinaryWriter(mstream));
            executable = mstream.ToArray();
            debugSymbols = null;
        }
        internal unsafe static void AddWin32Icon(Module/*!*/ module, string win32IconFilePath)
        {
            if (module == null || win32IconFilePath == null) { Debug.Assert(false); return; }
            using (System.IO.FileStream resStream = File.OpenRead(win32IconFilePath))
            {
                Writer.AddWin32Icon(module, resStream);
            }
        }
        internal unsafe static void AddWin32Icon(Module/*!*/ module, Stream win32IconStream)
        {
            if (module == null || win32IconStream == null) { Debug.Assert(false); return; }
            long size = win32IconStream.Length;
            if (size > int.MaxValue) throw new System.IO.FileLoadException();
            int n = (int)size;
            byte[] buffer = new byte[n];
            win32IconStream.Read(buffer, 0, n);
            byte* pb = (byte*)Marshal.AllocHGlobal(n);
            for (int i = 0; i < n; i++) pb[i] = buffer[i];
            MemoryCursor cursor = new MemoryCursor(pb, n/*, module*/);
            if (module.Win32Resources == null) module.Win32Resources = new Win32ResourceList();
            int reserved = cursor.ReadUInt16();
            if (reserved != 0) throw new NullReferenceException();
            int resourceType = cursor.ReadUInt16();
            if (resourceType != 1) throw new NullReferenceException();
            int imageCount = cursor.ReadUInt16();
            BinaryWriter indexHeap = new BinaryWriter(new MemoryStream());
            indexHeap.Write((ushort)0); //Reserved
            indexHeap.Write((ushort)1); //idType
            indexHeap.Write((ushort)imageCount);
            Win32Resource resource = new Win32Resource();
            for (int i = 0; i < imageCount; i++)
            {
                resource = new Win32Resource();
                resource.CodePage = 0;
                resource.Id = module.Win32Resources.Count + 2;
                resource.LanguageId = 0;
                resource.Name = null;
                resource.TypeId = 3;
                resource.TypeName = null;
                indexHeap.Write(cursor.ReadByte()); //width
                indexHeap.Write(cursor.ReadByte()); //height
                indexHeap.Write(cursor.ReadByte()); //color count
                indexHeap.Write(cursor.ReadByte()); //reserved
                indexHeap.Write(cursor.ReadUInt16()); //planes
                indexHeap.Write(cursor.ReadUInt16()); //bit count
                int len = cursor.ReadInt32();
                int offset = cursor.ReadInt32();
                indexHeap.Write((int)len);
                indexHeap.Write((int)module.Win32Resources.Count + 2);
                MemoryCursor c = new MemoryCursor(cursor);
                c.Position = offset;
                resource.Data = c.ReadBytes(len);
                module.Win32Resources.Add(resource);
            }
            resource.CodePage = 0;
            resource.Data = indexHeap.BaseStream.ToArray();
            resource.Id = 0x7f00;
            resource.LanguageId = 0;
            resource.Name = null;
            resource.TypeId = 0xe;
            resource.TypeName = null;
            module.Win32Resources.Add(resource);
        }
        internal unsafe static void AddWin32ResourceFileToModule(Module/*!*/ module, string/*!*/ win32ResourceFilePath)
        {
            if (module == null || win32ResourceFilePath == null) { Debug.Assert(false); return; }
            using (System.IO.FileStream resStream = File.OpenRead(win32ResourceFilePath))
            {
                Writer.AddWin32ResourceFileToModule(module, resStream);
            }
        }
        internal unsafe static void AddWin32ResourceFileToModule(Module/*!*/ module, Stream/*!*/ win32ResourceStream)
        {
            if (module == null || win32ResourceStream == null) { Debug.Assert(false); return; }
            long size = win32ResourceStream.Length;
            if (size > int.MaxValue) throw new System.IO.FileLoadException();
            int n = (int)size;
            byte[] buffer = new byte[n];
            win32ResourceStream.Read(buffer, 0, n);
            byte* pb = (byte*)Marshal.AllocHGlobal(n);
            for (int i = 0; i < n; i++) pb[i] = buffer[i];
            MemoryCursor cursor = new MemoryCursor(pb, n/*, module*/);
            if (module.Win32Resources == null) module.Win32Resources = new Win32ResourceList();
            while (cursor.Position < n)
            {
                Win32Resource resource = new Win32Resource();
                resource.CodePage = 0; //Review: Should this be settable?
                int dataSize = cursor.ReadInt32();
                cursor.ReadUInt32(); //headerSize
                if (cursor.Int16(0) == -1)
                {
                    cursor.ReadInt16();
                    resource.TypeId = cursor.ReadUInt16();
                    resource.TypeName = null;
                }
                else
                {
                    resource.TypeId = 0;
                    resource.TypeName = cursor.ReadUTF16();
                }
                if (cursor.Int16(0) == -1)
                {
                    cursor.ReadInt16();
                    resource.Id = cursor.ReadUInt16();
                    resource.Name = null;
                }
                else
                {
                    resource.Id = 0;
                    resource.Name = cursor.ReadUTF16();
                }
                cursor.ReadUInt32(); //dataVersion
                cursor.ReadUInt16(); //memoryFlags
                resource.LanguageId = cursor.ReadUInt16();
                cursor.ReadUInt32(); //version
                cursor.ReadUInt32(); //characteristics
                resource.Data = cursor.ReadBytes(dataSize);
                if (resource.Data != null)
                    module.Win32Resources.Add(resource);
            }
        }
        internal static void AddWin32VersionInfo(Module/*!*/ module, CompilerOptions/*!*/ options)
        {
            if (module == null || options == null) { Debug.Assert(false); return; }
            Win32Resource resource = new Win32Resource();
            resource.CodePage = 0;
            resource.Id = 1;
            resource.LanguageId = 0;
            resource.Name = null;
            resource.TypeId = 0x10;
            resource.TypeName = null;
            resource.Data = Writer.FillInVsVersionStructure(module, options);
            if (module.Win32Resources == null) module.Win32Resources = new Win32ResourceList();
            module.Win32Resources.Add(resource);
        }
        private static byte[] FillInVsVersionStructure(Module/*!*/ module, CompilerOptions/*!*/ options)
        {
            AssemblyNode assembly = module as AssemblyNode;
            BinaryWriter data = new BinaryWriter(new MemoryStream(), Encoding.Unicode);
            data.Write((ushort)0); //Space for length
            data.Write((ushort)0x34); //VS_FIXEDFILEINFO length
            data.Write((ushort)0); //Type of data in version resource
            data.Write("VS_VERSION_INFO", true);
            data.Write((ushort)0); //Padding to 4 byte boundary
            // VS_FIXEDFILEINFO starts here
            data.Write((uint)0xFEEF04BD); //Signature
            data.Write((uint)0x00010000); //Version of VS_FIXEDFILEINFO
            Version fileVersion = Writer.ParseVersion(options.TargetInformation.Version, true);
            if (fileVersion == null && assembly != null) fileVersion = assembly.Version;
            if (fileVersion == null) fileVersion = new Version();
            data.Write((ushort)fileVersion.Minor);
            data.Write((ushort)fileVersion.Major);
            data.Write((ushort)fileVersion.Revision);
            data.Write((ushort)fileVersion.Build);
            Version productVersion = Writer.ParseVersion(options.TargetInformation.ProductVersion, true);
            if (productVersion == null) productVersion = fileVersion;
            data.Write((ushort)productVersion.Minor);
            data.Write((ushort)productVersion.Major);
            data.Write((ushort)productVersion.Revision);
            data.Write((ushort)productVersion.Build);
            data.Write((uint)0x3f); //FileFlagsMask
            data.Write((uint)0x0); //FileFlags
            data.Write((uint)0x4); //OS: Win32 (After all, this is a Win32 resource.)
            if (options.GenerateExecutable)
                data.Write((uint)1); //App
            else
                data.Write((uint)2); //Dll
            data.Write((uint)0); //File subtype
            data.Write((ulong)0); //File Date
            // VarFileInfo
            data.Write((ushort)0x44); //Length of VarFileInfo
            data.Write((ushort)0x0); //Length of value
            data.Write((ushort)0x1); //type (text)
            data.Write("VarFileInfo", true);
            data.Write((ushort)0); //padding to 4 byte boundary
            // Var
            data.Write((ushort)0x24); //Length of Var
            data.Write((ushort)0x04); //length of Value
            data.Write((ushort)0); //Type (binary)
            data.Write("Translation", true);
            data.Write((uint)0); //Padding
            data.Write((ushort)0x4b0); //Code Page for Unicode
            // StringFileInfo
            int positionOfInfoLength = data.BaseStream.Position;
            data.Write((ushort)0); //length of rest of resource
            data.Write((ushort)0); //Value length, always 0
            data.Write((ushort)1); //Type (text)
            data.Write("StringFileInfo", true);
            // StringInfo
            int stringInfoLengthPos = data.BaseStream.Position;
            data.Write((ushort)0); //Space for length
            data.Write((ushort)0); //Value length, always 0
            data.Write((ushort)1); //Type (text)
            data.Write("000004b0", true); //Code page for Unicode
            Writer.WriteVersionString(data, options.TargetInformation.Description, "Comments");
            Writer.WriteVersionString(data, options.TargetInformation.Company, "CompanyName");
            Writer.WriteVersionString(data, options.TargetInformation.Title, "FileDescription");
            Writer.WriteVersionString(data, Writer.ConvertToString(fileVersion), "FileVersion");
            string fileName = module.Name + (options.GenerateExecutable ? ".exe" : ".dll");
            Writer.WriteVersionString(data, fileName, "InternalName");
            Writer.WriteVersionString(data, options.TargetInformation.Copyright, "LegalCopyright");
            Writer.WriteVersionString(data, options.TargetInformation.Trademark, "LegalTrademarks");
            Writer.WriteVersionString(data, fileName, "OriginalFilename");
            Writer.WriteVersionString(data, options.TargetInformation.Product, "ProductName");
            Writer.WriteVersionString(data, Writer.ConvertToString(productVersion), "ProductVersion");
            if (assembly != null)
                Writer.WriteVersionString(data, assembly.Version == null ? "" : assembly.Version.ToString(), "Assembly Version");
            int len = data.BaseStream.Position;
            data.BaseStream.Position = stringInfoLengthPos;
            data.Write((ushort)(len - stringInfoLengthPos));
            data.BaseStream.Position = 0;
            data.Write((ushort)len);
            data.BaseStream.Position = positionOfInfoLength;
            data.Write((ushort)len - positionOfInfoLength);
            return data.BaseStream.ToArray();
        }
        private static void WriteVersionString(BinaryWriter/*!*/ data, string value, string/*!*/ key)
        {
            if (value == null) return;
            int totalLength = 6;
            totalLength += key.Length * 2;
            totalLength += 4 - (totalLength % 4);
            totalLength += value.Length * 2;
            totalLength += 4 - (totalLength % 4);
            data.Write((ushort)totalLength);
            data.Write((ushort)(value.Length + 1));
            data.Write((ushort)1); //Type (text)
            data.Write(key, true);
            if (data.BaseStream.Position % 4 != 0) data.Write((char)0);
            data.Write(value, true);
            if (data.BaseStream.Position % 4 != 0) data.Write((char)0);
        }
        private static string/*!*/ ConvertToString(Version/*!*/ version)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(version.Major.ToString());
            if (version.Minor != 0 || version.Build != 0 || version.Revision != 0)
            {
                sb.Append('.');
                sb.Append(version.Minor.ToString());
            }
            if (version.Build != 0 || version.Revision != 0)
            {
                sb.Append('.');
                sb.Append(version.Build.ToString());
            }
            if (version.Revision != 0)
            {
                sb.Append('.');
                sb.Append(version.Revision.ToString());
            }
            return sb.ToString();
        }
        private static Version ParseVersion(string vString, bool allowWildcards)
        {
            if (vString == null) return null;
            ushort major = 1;
            ushort minor = 0;
            ushort build = 0;
            ushort revision = 0;
            try
            {
                int n = vString.Length;
                int i = vString.IndexOf('.', 0);
                if (i < 0) throw new FormatException();
                major = UInt16.Parse(vString.Substring(0, i), CultureInfo.InvariantCulture);
                int j = vString.IndexOf('.', i + 1);
                if (j < i + 1)
                    minor = UInt16.Parse(vString.Substring(i + 1, n - i - 1), CultureInfo.InvariantCulture);
                else
                {
                    minor = UInt16.Parse(vString.Substring(i + 1, j - i - 1), CultureInfo.InvariantCulture);
                    if (vString[j + 1] == '*' && allowWildcards)
                    {
                        if (j + 1 < n - 1) return null;
                        build = Writer.DaysSince2000();
                        revision = Writer.SecondsSinceMidnight();
                    }
                    else
                    {
                        int k = vString.IndexOf('.', j + 1);
                        if (k < j + 1)
                            build = UInt16.Parse(vString.Substring(j + 1, n - j - 1), CultureInfo.InvariantCulture);
                        else
                        {
                            build = UInt16.Parse(vString.Substring(j + 1, k - j - 1), CultureInfo.InvariantCulture);
                            if (vString[k + 1] == '*' && allowWildcards)
                            {
                                if (j + 1 < n - 1) return null;
                                revision = Writer.SecondsSinceMidnight();
                            }
                            else
                                revision = UInt16.Parse(vString.Substring(k + 1, n - k - 1), CultureInfo.InvariantCulture);
                        }
                    }
                }
            }
            catch (FormatException)
            {
                major = minor = build = revision = UInt16.MaxValue;
            }
            catch (OverflowException)
            {
                major = minor = build = revision = UInt16.MaxValue;
            }
            if (major == UInt16.MaxValue && minor == UInt16.MaxValue && build == UInt16.MaxValue && revision == UInt16.MaxValue)
            {
                return null;
            }
            return new Version(major, minor, build, revision);
        }
        private static ushort DaysSince2000()
        {
            return (ushort)(DateTime.Now - new DateTime(2000, 1, 1)).Days;
        }
        private static ushort SecondsSinceMidnight()
        {
            TimeSpan sinceMidnight = DateTime.Now - DateTime.Today;
            return (ushort)((sinceMidnight.Hours * 60 * 60 + sinceMidnight.Minutes * 60 + sinceMidnight.Seconds) / 2);
        }

    }
}
#endif
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.