diff options
Diffstat (limited to 'tools/Sandcastle/Source/CCI/Writer.cs')
-rw-r--r-- | tools/Sandcastle/Source/CCI/Writer.cs | 6397 |
1 files changed, 6397 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/CCI/Writer.cs b/tools/Sandcastle/Source/CCI/Writer.cs new file mode 100644 index 0000000..28a3668 --- /dev/null +++ b/tools/Sandcastle/Source/CCI/Writer.cs @@ -0,0 +1,6397 @@ +// 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 |