// 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
|