diff options
Diffstat (limited to 'tools/Sandcastle/Source/CCI/Reader.cs')
-rw-r--r-- | tools/Sandcastle/Source/CCI/Reader.cs | 6074 |
1 files changed, 6074 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/CCI/Reader.cs b/tools/Sandcastle/Source/CCI/Reader.cs new file mode 100644 index 0000000..713e9b7 --- /dev/null +++ b/tools/Sandcastle/Source/CCI/Reader.cs @@ -0,0 +1,6074 @@ +// 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. + +using System; +using System.Collections; +#if FxCop +using System.Collections.Generic; +using AssemblyReferenceList = Microsoft.Cci.AssemblyReferenceCollection; +using AttributeList = Microsoft.Cci.AttributeNodeCollection; +using BlockList = Microsoft.Cci.BlockCollection; +using ExpressionList = Microsoft.Cci.ExpressionCollection; +using InstructionList = Microsoft.Cci.InstructionCollection; +using Int32List = System.Collections.Generic.List<int>; +using InterfaceList = Microsoft.Cci.InterfaceCollection; +using LocalList = Microsoft.Cci.LocalCollection; +using MemberList = Microsoft.Cci.MemberCollection; +using MethodList = Microsoft.Cci.MethodCollection; +using ModuleReferenceList = Microsoft.Cci.ModuleReferenceCollection; +using NamespaceList = Microsoft.Cci.NamespaceCollection; +using ParameterList = Microsoft.Cci.ParameterCollection; +using ResourceList = Microsoft.Cci.ResourceCollection; +using SecurityAttributeList = Microsoft.Cci.SecurityAttributeCollection; +using StatementList = Microsoft.Cci.StatementCollection; +using TypeNodeList = Microsoft.Cci.TypeNodeCollection; +using Win32ResourceList = Microsoft.Cci.Win32ResourceCollection; +using Property = Microsoft.Cci.PropertyNode; +using Module = Microsoft.Cci.ModuleNode; +using Class = Microsoft.Cci.ClassNode; +using Interface = Microsoft.Cci.InterfaceNode; +using Event = Microsoft.Cci.EventNode; +using Return = Microsoft.Cci.ReturnNode; +using Throw = Microsoft.Cci.ThrowNode; +#endif +#if UseSingularityPDB +using Microsoft.Singularity.PdbInfo; +using Microsoft.Singularity.PdbInfo.Features; +#endif +#if CCINamespace +using Microsoft.Cci; +#else +using System.Compiler; +#endif +using System.Diagnostics; +using System.Globalization; +using Marshal = System.Runtime.InteropServices.Marshal; +using System.Runtime.InteropServices; +using System.IO; + +#if CCINamespace +namespace Microsoft.Cci.Metadata{ +#else +namespace System.Compiler.Metadata +{ +#endif + +#if !ROTOR && !UseSingularityPDB + enum CorOpenFlags : uint + { + ofRead = 0x00000000, // Open scope for read + ofWrite = 0x00000001, // Open scope for write. + ofCopyMemory = 0x00000002, // Open scope with memory. Ask metadata to maintain its own copy of memory. + ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image + ofNoTypeLib = 0x00000080, // Don't OpenScope on a typelib. + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("809c652e-7396-11d2-9771-00A0C9B4D50C")] + interface IMetaDataDispenser + { + void DefineScope(ref Guid clsid, uint createFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object retval); + [PreserveSig] + int OpenScope(string scope, uint openFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object import); + void OpenScopeOnMemory(IntPtr data, uint dataSize, uint openFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object retval); + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("AA544D42-28CB-11d3-BD22-0000F80849BD")] + interface ISymUnmanagedBinder + { + [PreserveSig] + int GetReaderForFile([MarshalAs(UnmanagedType.IUnknown)] object importer, string filename, string searchPath, out ISymUnmanagedReader reader); + ISymUnmanagedReader GetReaderForStream([MarshalAs(UnmanagedType.IUnknown)] object importer, [MarshalAs(UnmanagedType.IUnknown)] object stream); + } + [ComImport, Guid("ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(false)] + interface ISymUnmanagedBinder2 : ISymUnmanagedBinder + { + void GetReaderForFile(IntPtr importer, [MarshalAs(UnmanagedType.LPWStr)] String filename, [MarshalAs(UnmanagedType.LPWStr)] String SearchPath, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader retVal); + void GetReaderFromStream(IntPtr importer, IntPtr stream, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader retVal); + [PreserveSig] + int GetReaderForFile2([MarshalAs(UnmanagedType.IUnknown)] object importer, [MarshalAs(UnmanagedType.LPWStr)] String fileName, [MarshalAs(UnmanagedType.LPWStr)] String searchPath, int searchPolicy, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader pRetVal); + // void GetReaderForFile3(IntPtr importer, [MarshalAs(UnmanagedType.LPWStr)] String fileName, [MarshalAs(UnmanagedType.LPWStr)] String searchPath, int searchPolicy, IntPtr callback, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader pRetVal); + } + [ComImport, Guid("AA544D41-28CB-11d3-BD22-0000F80849BD")] + class CorSymBinder + { + } + [ComImport, Guid("0A29FF9E-7F9C-4437-8B11-F424491E3931")] + class CorSymBinder2 + { + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5")] + interface ISymUnmanagedReader + { + ISymUnmanagedDocument GetDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType); + void GetDocuments(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] docs); + uint GetUserEntryPoint(); + [PreserveSig] + int GetMethod(uint token, ref ISymUnmanagedMethod method); + ISymUnmanagedMethod GetMethodByVersion(uint token, int version); + void GetVariables(uint parent, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ISymUnmanagedVariable[] vars); + void GetGlobalVariables(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] vars); + ISymUnmanagedMethod GetMethodFromDocumentPosition(ISymUnmanagedDocument document, uint line, uint column); + void GetSymAttribute(uint parent, string name, ulong size, ref uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer); + void GetNamespaces(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] namespaces); + void Initialize([MarshalAs(UnmanagedType.IUnknown)] object importer, string filename, string searchPath, [MarshalAs(UnmanagedType.IUnknown)] object stream); + void UpdateSymbolStore(string filename, [MarshalAs(UnmanagedType.IUnknown)] object stream); + void ReplaceSymbolStore(string filename, [MarshalAs(UnmanagedType.IUnknown)] object stream); + void GetSymbolStoreFileName(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] name); + void GetMethodsFromDocumentPosition(ISymUnmanagedDocument document, uint line, uint column, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] ISymUnmanagedMethod[] retval); + void GetDocumentVersion(ISymUnmanagedDocument doc, out int version, out bool isLatest); + void GetMethodVersion(ISymUnmanagedMethod method, out int version); + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B62B923C-B500-3158-A543-24F307A8B7E1")] + interface ISymUnmanagedMethod + { + uint GetToken(); + uint GetSequencePointCount(); + ISymUnmanagedScope GetRootScope(); + ISymUnmanagedScope GetScopeFromOffset(uint offset); + uint Getoffset(ISymUnmanagedDocument document, uint line, uint column); + void GetRanges(ISymUnmanagedDocument document, uint line, uint column, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] ranges); + void GetParameters(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] parms); + IntPtr GetNamespace(); + bool GetSourceStartEnd([MarshalAs(UnmanagedType.LPArray, SizeConst = 2)] ISymUnmanagedDocument[] docs, [MarshalAs(UnmanagedType.LPArray)] uint[] lines, [MarshalAs(UnmanagedType.LPArray)] uint[] columns); + void GetSequencePoints(uint size, out uint length, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] offsets, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, SizeParamIndex = 0)] IntPtr[] documents, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] lines, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] columns, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] endLines, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] endColumns); + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08")] + interface ISymUnmanagedDocument + { + void GetURL(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] url); + void GetDocumentType(out Guid retval); + void GetLanguage(out Guid retval); + void GetLanguageVendor(out Guid retval); + void GetCheckSumAlgorithmId(out Guid retval); + void GetCheckSum(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] data); + uint FindClosestLine(uint line); + bool HasEmbeddedSource(); + uint GetSourceLength(); + void GetSourceRange(uint startLine, uint startColumn, uint endLine, uint endColumn, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] source); + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB")] + interface ISymUnmanagedVariable + { + void GetName(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] name); + uint GetAttributes(); + void GetSignature(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] name); + uint GetAddressKind(); + uint GetAddressField1(); + uint GetAddressField2(); + uint GetAddressField3(); + uint GetStartOffset(); + uint GetEndOffset(); + } + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("68005D0F-B8E0-3B01-84D5-A11A94154942")] + interface ISymUnmanagedScope + { + ISymUnmanagedMethod GetMethod(); + ISymUnmanagedScope GetParent(); + void GetChildren(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] children); + uint GetStartOffset(); + uint GetEndOffset(); + uint GetLocalCount(); + void GetLocals(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] locals); + void GetNamespaces(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] namespaces); + } +#endif + internal sealed class UnmanagedBuffer : IDisposable + { + internal IntPtr Pointer; + internal UnmanagedBuffer(int length) + { + this.Pointer = Marshal.AllocHGlobal(length); + } + public void Dispose() + { + if (this.Pointer != IntPtr.Zero) + Marshal.FreeHGlobal(this.Pointer); + this.Pointer = IntPtr.Zero; + GC.SuppressFinalize(this); + } + ~UnmanagedBuffer() + { + this.Dispose(); + } + } + internal unsafe class Reader : IDisposable + { + private string directory; + private string fileName; + private bool doNotLockFile; + private Module/*!*/ module = new Module(); + internal TypeNode currentType; + private long sortedTablesMask; + internal MetadataReader/*!*/ tables; + private UnmanagedBuffer unmanagedBuffer; + private int bufferLength; + private IDictionary/*!*/ localAssemblyCache; //use for simple names + internal readonly static IDictionary/*!*/ StaticAssemblyCache = new SynchronizedWeakDictionary(); //use for strong names + private bool useStaticCache; + //^ [Microsoft.Contracts.SpecInternal] + private TrivialHashtable namespaceTable; + internal NamespaceList namespaceList; +#if UseSingularityPDB + internal PdbFunction[] pdbFunctions; +#elif !ROTOR + internal ISymUnmanagedReader debugReader; +#endif +#if FxCop + internal static bool probeGAC = true; +#endif + internal bool getDebugSymbols; + private bool getDebugSymbolsFailed; + private TypeNodeList currentTypeParameters; + private TypeNodeList currentMethodTypeParameters; + internal bool preserveShortBranches; +#if !MinimalReader + internal unsafe Reader(byte[]/*!*/ buffer, IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches) + { + Debug.Assert(buffer != null); + if (localAssemblyCache == null) localAssemblyCache = new Hashtable(); + this.localAssemblyCache = localAssemblyCache; + this.getDebugSymbols = getDebugInfo; + this.doNotLockFile = false; + this.useStaticCache = useStaticCache; + this.preserveShortBranches = preserveShortBranches; + int n = this.bufferLength = buffer.Length; + this.unmanagedBuffer = new UnmanagedBuffer(n); + //^ base(); + byte* pb = (byte*)this.unmanagedBuffer.Pointer; + for (int i = 0; i < n; i++) *pb++ = buffer[i]; + } +#endif + internal Reader(string/*!*/ fileName, IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches) + { + if (localAssemblyCache == null) localAssemblyCache = new Hashtable(); + this.localAssemblyCache = localAssemblyCache; + fileName = System.IO.Path.GetFullPath(fileName); + this.fileName = fileName; + this.directory = System.IO.Path.GetDirectoryName(fileName); + this.getDebugSymbols = getDebugInfo; + this.doNotLockFile = doNotLockFile; + this.useStaticCache = useStaticCache; + this.preserveShortBranches = preserveShortBranches; + //^ base(); + } + internal Reader(IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches) + { + if (localAssemblyCache == null) localAssemblyCache = new Hashtable(); + this.localAssemblyCache = localAssemblyCache; + this.directory = System.IO.Directory.GetCurrentDirectory(); + this.getDebugSymbols = getDebugInfo; + this.doNotLockFile = doNotLockFile; + this.useStaticCache = useStaticCache; + this.preserveShortBranches = preserveShortBranches; + //^ base(); + } + public void Dispose() + { + if (this.unmanagedBuffer != null) + this.unmanagedBuffer.Dispose(); + this.unmanagedBuffer = null; + if (this.tables != null) + this.tables.Dispose(); + //this.tables = null; +#if !ROTOR && !UseSingularityPDB + if (this.debugReader != null) + Marshal.ReleaseComObject(this.debugReader); + this.debugReader = null; +#endif + } + private unsafe void SetupReader() + { + Debug.Assert(this.localAssemblyCache != null); +#if !ROTOR + if (this.doNotLockFile) + { +#endif + using (System.IO.FileStream inputStream = new System.IO.FileStream(this.fileName, + System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)) + { + this.ReadFileIntoUnmanagedBuffer(inputStream); + } +#if !ROTOR + } + if (this.unmanagedBuffer == null) + this.tables = new MetadataReader(this.fileName); //Uses a memory map that locks the file + else +#endif + this.tables = new MetadataReader((byte*)this.unmanagedBuffer.Pointer, this.bufferLength); + //^ assume this.tables.tablesHeader != null; + this.sortedTablesMask = this.tables.tablesHeader.maskSorted; + } +#if !ROTOR + [DllImport("kernel32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern unsafe bool ReadFile(IntPtr FileHandle, byte* Buffer, int NumberOfBytesToRead, int* NumberOfBytesRead, IntPtr Overlapped); +#endif + private unsafe void ReadFileIntoUnmanagedBuffer(System.IO.FileStream/*!*/ inputStream) + { + long size = inputStream.Seek(0, System.IO.SeekOrigin.End); + if (size > int.MaxValue) throw new System.IO.FileLoadException(); + inputStream.Seek(0, System.IO.SeekOrigin.Begin); + int n = (int)size; + this.bufferLength = n; + this.unmanagedBuffer = new UnmanagedBuffer(n); + byte* pb = (byte*)this.unmanagedBuffer.Pointer; +#if !ROTOR +#if WHIDBEY && !OldWhidbey + if (!Reader.ReadFile(inputStream.SafeFileHandle.DangerousGetHandle(), pb, n, &n, IntPtr.Zero)) throw new System.IO.FileLoadException(); +#else + if (!Reader.ReadFile(inputStream.Handle, pb, n, &n, IntPtr.Zero)) throw new System.IO.FileLoadException(); +#endif +#else + //Read a fixed length block at a time, so that the GC does not come under pressure from lots of large byte arrays. + int bufferLen = 8096; + byte[] buffer = new byte[bufferLen]; + while (n > 0){ + if (n < bufferLen) bufferLen = n; + inputStream.Read(buffer, 0, bufferLen); + for (int i = 0; i < bufferLen; i++) *pb++ = buffer[i]; + n -= bufferLen; + } +#endif + } + internal void SetupDebugReader(string filename, string pdbSearchPath) + { +#if UseSingularityPDB + string pdbFileName = BetterPath.ChangeExtension(filename, "pdb"); + this.getDebugSymbolsFailed = true; + //TODO: use search path + if (System.IO.File.Exists(pdbFileName)) { + using (System.IO.FileStream inputStream = new System.IO.FileStream(pdbFileName, + System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)) { + this.pdbFunctions = PdbFile.LoadFunctions(inputStream, true); + this.getDebugSymbolsFailed = false; + } + } +#elif !ROTOR + if (filename == null) return; + CorSymBinder binderObj1 = null; + CorSymBinder2 binderObj2 = null; + getDebugSymbolsFailed = false; + object importer = null; + try + { + int hresult = 0; + try + { + binderObj2 = new CorSymBinder2(); + ISymUnmanagedBinder2 binder2 = (ISymUnmanagedBinder2)binderObj2; +#if !NoWriter + importer = new Ir2md(new Module()); +#else + importer = new EmptyImporter(); +#endif + hresult = binder2.GetReaderForFile(importer, filename, pdbSearchPath, out this.debugReader); + } + catch (COMException e) + { + // could not instantiate ISymUnmanagedBinder2, fall back to ISymUnmanagedBinder + if ((uint)e.ErrorCode == 0x80040111) + { + binderObj1 = new CorSymBinder(); + ISymUnmanagedBinder binder = (ISymUnmanagedBinder)binderObj1; + hresult = binder.GetReaderForFile(importer, filename, null, out this.debugReader); + } + else + { + throw; + } + } + switch ((uint)hresult) + { + case 0x0: break; + case 0x806d0005: // EC_NOT_FOUND + case 0x806d0014: // EC_INVALID_EXE_TIMESTAMP +#if FxCop + this.getDebugSymbols = false; + this.getDebugSymbolsFailed = true; +#else + // Sometimes GetReaderForFile erroneously reports missing pdb files as being "out of date", + // so we check if the file actually exists before reporting the error. + // The mere absence of a pdb file is not an error. If not present, do not report. + if (System.IO.File.Exists(System.IO.Path.ChangeExtension(filename, ".pdb"))) + throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExceptionStrings.PdbAssociatedWithFileIsOutOfDate, filename)); +#endif + break; + default: + throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.GetReaderForFileReturnedUnexpectedHResult, hresult.ToString("X"))); + } +#if !FxCop + } + catch (Exception e) + { + this.getDebugSymbols = false; + this.getDebugSymbolsFailed = true; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); +#endif + } + finally + { + if (binderObj1 != null) Marshal.ReleaseComObject(binderObj1); + if (binderObj2 != null) Marshal.ReleaseComObject(binderObj2); + } +#endif // !ROTOR + } + private AssemblyNode ReadAssembly() + { + try + { + AssemblyNode assembly = new AssemblyNode(new Module.TypeNodeProvider(this.GetTypeFromName), + new Module.TypeNodeListProvider(this.GetTypeList), new Module.CustomAttributeProvider(this.GetCustomAttributesFor), + new Module.ResourceProvider(this.GetResources), this.directory); + assembly.reader = this; + this.ReadModuleProperties(assembly); + this.ReadAssemblyProperties(assembly); //Hashvalue, Name, etc. + this.module = assembly; + this.ReadAssemblyReferences(assembly); + this.ReadModuleReferences(assembly); + AssemblyNode cachedAssembly = this.GetCachedAssembly(assembly); + if (cachedAssembly != null) return cachedAssembly; + if (this.getDebugSymbols) assembly.SetupDebugReader(null); +#if !MinimalReader + assembly.AfterAssemblyLoadProcessing(); +#endif + return assembly; +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return null; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + return this.module as AssemblyNode; + } +#else + }finally{} +#endif + } + private AssemblyNode GetCachedAssembly(AssemblyNode/*!*/ assembly) + { + //Always return the one true mscorlib. Things get too weird if more than one mscorlib is being read at the same time. + //if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assembly.Name && CoreSystemTypes.SystemAssembly.reader != null) { + // if (CoreSystemTypes.SystemAssembly.reader != this) { + // if (this.getDebugSymbols && !CoreSystemTypes.SystemAssembly.reader.getDebugSymbols && !CoreSystemTypes.SystemAssembly.reader.getDebugSymbolsFailed) + // CoreSystemTypes.SystemAssembly.SetupDebugReader(null); + // this.Dispose(); + // } + // return CoreSystemTypes.SystemAssembly; + //} + if (assembly.PublicKeyOrToken == null || assembly.PublicKeyOrToken.Length == 0) + { + AssemblyNode cachedAssembly = null; + if (assembly.Location != null) + cachedAssembly = this.localAssemblyCache[assembly.Location] as AssemblyNode; + if (cachedAssembly == null && assembly.Name != null) + { + cachedAssembly = this.localAssemblyCache[assembly.Name] as AssemblyNode; + if (cachedAssembly != null && assembly.Location != null) + this.localAssemblyCache[assembly.Location] = cachedAssembly; + } + if (cachedAssembly != null) + { + if (cachedAssembly.reader != this && cachedAssembly.reader != null) + { + if (this.getDebugSymbols && !cachedAssembly.reader.getDebugSymbols && !cachedAssembly.reader.getDebugSymbolsFailed) + cachedAssembly.SetupDebugReader(null); + this.Dispose(); + } + return cachedAssembly; + } + lock (Reader.StaticAssemblyCache) + { + if (assembly.Name != null) + this.localAssemblyCache[assembly.Name] = assembly; + if (this.fileName != null) + this.localAssemblyCache[this.fileName] = assembly; + } + } + else + { + string assemblyStrongName = assembly.StrongName; + AssemblyNode cachedAssembly = null; + if (this.useStaticCache) + { + //See if assembly is a platform assembly (and apply unification) + AssemblyReference assemblyReference = new AssemblyReference(assembly); + AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(assemblyReference.Name).UniqueIdKey]; + if (aRef != null && assemblyReference.Version != null && aRef.Version >= assemblyReference.Version && aRef.MatchesIgnoringVersion(assemblyReference)) + { + AssemblyNode platformAssembly = aRef.assembly; + if (platformAssembly == null) + { + Debug.Assert(aRef.Location != null); + if (Path.GetFullPath(aRef.Location) == assembly.Location) + { + if (aRef.Version != assemblyReference.Version) + { + HandleError(assembly, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.BadTargetPlatformLocation, assembly.Name, TargetPlatform.PlatformAssembliesLocation, assembly.Version, aRef.Version)); + } + lock (Reader.StaticAssemblyCache) + { + Reader.StaticAssemblyCache[assemblyStrongName] = assembly; + if (aRef.Location != null) + Reader.StaticAssemblyCache[aRef.Location] = assembly; + } + return null; //Prevents infinite recursion + } + platformAssembly = AssemblyNode.GetAssembly(aRef.Location, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + } + if (platformAssembly != null) + { + lock (Reader.StaticAssemblyCache) + { + if (aRef.Location != null) + Reader.StaticAssemblyCache[aRef.Location] = platformAssembly; + Reader.StaticAssemblyCache[assemblyStrongName] = platformAssembly; + } + return aRef.assembly = platformAssembly; + } + } + cachedAssembly = Reader.StaticAssemblyCache[assemblyStrongName] as AssemblyNode; + if (cachedAssembly != null) + { + if (aRef == null && assembly.FileLastWriteTimeUtc > cachedAssembly.FileLastWriteTimeUtc && + assembly.Location != null && cachedAssembly.Location != null && assembly.Location == cachedAssembly.Location) + { + lock (Reader.StaticAssemblyCache) + { + Reader.StaticAssemblyCache[assemblyStrongName] = assembly; + } + return null; + } + if (cachedAssembly.reader != this && cachedAssembly.reader != null) + { + if (this.getDebugSymbols && !cachedAssembly.reader.getDebugSymbols && !cachedAssembly.reader.getDebugSymbolsFailed) + cachedAssembly.SetupDebugReader(null); + this.Dispose(); + } + return cachedAssembly; + } + lock (Reader.StaticAssemblyCache) + { + Reader.StaticAssemblyCache[assemblyStrongName] = assembly; + if (this.fileName != null) + { + Reader.StaticAssemblyCache[this.fileName] = assembly; + } + } + } + else + { + cachedAssembly = this.localAssemblyCache[assemblyStrongName] as AssemblyNode; + if (cachedAssembly != null) + { + if (assembly.FileLastWriteTimeUtc > cachedAssembly.FileLastWriteTimeUtc && + assembly.Location != null && cachedAssembly.Location != null && assembly.Location == cachedAssembly.Location) + { + this.localAssemblyCache[assemblyStrongName] = assembly; + return null; + } + if (cachedAssembly.reader != this && cachedAssembly.reader != null) + { +#if UseSingularityPDB + if (this.getDebugSymbols && cachedAssembly.reader.pdbFunctions == null && !cachedAssembly.reader.getDebugSymbolsFailed) + cachedAssembly.SetupDebugReader(null); +#elif !ROTOR + if (this.getDebugSymbols && cachedAssembly.reader.debugReader == null && !cachedAssembly.reader.getDebugSymbolsFailed) + cachedAssembly.SetupDebugReader(null); +#endif + this.Dispose(); + } + return cachedAssembly; + } + this.localAssemblyCache[assemblyStrongName] = assembly; + if (this.fileName != null) this.localAssemblyCache[this.fileName] = assembly; + } + } + return null; + } + internal Module ReadModule() + { + try + { + if (this.fileName != null) + { + if (!System.IO.File.Exists(this.fileName)) return null; + AssemblyNode cachedAssembly; + if (this.useStaticCache) + { + cachedAssembly = Reader.StaticAssemblyCache[this.fileName] as AssemblyNode; + if (cachedAssembly != null && cachedAssembly.FileLastWriteTimeUtc == System.IO.File.GetLastWriteTimeUtc(this.fileName)) + { + this.Dispose(); + return cachedAssembly; + } + } + cachedAssembly = this.localAssemblyCache[this.fileName] as AssemblyNode; + if (cachedAssembly != null && cachedAssembly.FileLastWriteTimeUtc == System.IO.File.GetLastWriteTimeUtc(this.fileName)) + { + this.Dispose(); + return cachedAssembly; + } + } + this.SetupReader(); + if (this.tables.AssemblyTable.Length > 0) return this.ReadAssembly(); + Module module = this.module = new Module(new Module.TypeNodeProvider(this.GetTypeFromName), + new Module.TypeNodeListProvider(this.GetTypeList), new Module.CustomAttributeProvider(this.GetCustomAttributesFor), + new Module.ResourceProvider(this.GetResources)); + module.reader = this; + this.ReadModuleProperties(module); + this.module = module; + this.ReadAssemblyReferences(module); + this.ReadModuleReferences(module); + if (this.getDebugSymbols) this.SetupDebugReader(this.fileName, null); + return module; +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return null; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + return module; + } +#else + }finally{} +#endif + } + private void ReadModuleProperties(Module/*!*/ module) + { + ModuleRow[] mods = this.tables.ModuleTable; + if (mods.Length != 1) throw new InvalidMetadataException(ExceptionStrings.InvalidModuleTable); + ModuleRow mrow = mods[0]; + module.reader = this; + module.FileAlignment = this.tables.fileAlignment; + module.HashValue = this.tables.HashValue; + module.Kind = this.tables.moduleKind; + module.Location = this.fileName; + module.TargetRuntimeVersion = this.tables.targetRuntimeVersion; + module.LinkerMajorVersion = this.tables.linkerMajorVersion; + module.LinkerMinorVersion = this.tables.linkerMinorVersion; + module.MetadataFormatMajorVersion = this.tables.metadataFormatMajorVersion; + module.MetadataFormatMinorVersion = this.tables.metadataFormatMinorVersion; + module.Name = this.tables.GetString(mrow.Name); + module.Mvid = this.tables.GetGuid(mrow.Mvid); + module.PEKind = this.tables.peKind; + module.TrackDebugData = this.tables.TrackDebugData; + } + private void ReadAssemblyProperties(AssemblyNode/*!*/ assembly) + { + AssemblyRow assemblyRow = this.tables.AssemblyTable[0]; + assembly.HashAlgorithm = (AssemblyHashAlgorithm)assemblyRow.HashAlgId; + assembly.Version = new System.Version(assemblyRow.MajorVersion, assemblyRow.MinorVersion, assemblyRow.BuildNumber, assemblyRow.RevisionNumber); + assembly.Flags = (AssemblyFlags)assemblyRow.Flags; + assembly.PublicKeyOrToken = this.tables.GetBlob(assemblyRow.PublicKey); + assembly.ModuleName = assembly.Name; + assembly.Name = this.tables.GetString(assemblyRow.Name); + assembly.Culture = this.tables.GetString(assemblyRow.Culture); + if (this.fileName != null) + { + assembly.FileLastWriteTimeUtc = System.IO.File.GetLastWriteTimeUtc(this.fileName); + } + assembly.ContainingAssembly = assembly; + } + private void ReadAssemblyReferences(Module/*!*/ module) + { + AssemblyRefRow[] assems = this.tables.AssemblyRefTable; + int n = assems.Length; + AssemblyReferenceList assemblies = module.AssemblyReferences = new AssemblyReferenceList(n); + for (int i = 0; i < n; i++) + { + AssemblyRefRow arr = assems[i]; + AssemblyReference assemRef = new AssemblyReference(); + assemRef.Version = new System.Version(arr.MajorVersion, arr.MinorVersion, arr.BuildNumber, arr.RevisionNumber); + assemRef.Flags = (AssemblyFlags)arr.Flags; + assemRef.PublicKeyOrToken = this.tables.GetBlob(arr.PublicKeyOrToken); + assemRef.Name = this.tables.GetString(arr.Name); + //if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assemRef.Name && + // assemRef.Version > CoreSystemTypes.SystemAssembly.Version){ + // HandleError(module, ExceptionStrings.ModuleOrAssemblyDependsOnMoreRecentVersionOfCoreLibrary); + //} + assemRef.Culture = this.tables.GetString(arr.Culture); + if (assemRef.Culture != null && assemRef.Culture.Length == 0) assemRef.Culture = null; + assemRef.HashValue = this.tables.GetBlob(arr.HashValue); + assemRef.Reader = this; + assems[i].AssemblyReference = assemRef; + assemblies.Add(assemRef); + } + } + private void ReadModuleReferences(Module/*!*/ module) + { + FileRow[] files = this.tables.FileTable; + ModuleRefRow[] modRefs = this.tables.ModuleRefTable; + int n = modRefs.Length; + ModuleReferenceList modules = module.ModuleReferences = new ModuleReferenceList(n); + for (int i = 0; i < n; i++) + { + Module mod; + int nameIndex = modRefs[i].Name; + string name = this.tables.GetString(nameIndex); + string dir = BetterPath.GetDirectoryName(this.module.Location); + string location = BetterPath.Combine(dir, name); + for (int j = 0, m = files == null ? 0 : files.Length; j < m; j++) + { + if (files[j].Name != nameIndex) continue; + if ((files[j].Flags & (int)FileFlags.ContainsNoMetaData) == 0) + mod = Module.GetModule(location, this.doNotLockFile, this.getDebugSymbols, false); + else + mod = null; + if (mod == null) + { + mod = new Module(); + mod.Name = name; + mod.Location = location; + mod.Kind = ModuleKindFlags.UnmanagedDynamicallyLinkedLibrary; + } + mod.HashValue = this.tables.GetBlob(files[j].HashValue); + mod.ContainingAssembly = module.ContainingAssembly; + modRefs[i].Module = mod; + modules.Add(new ModuleReference(name, mod)); + goto nextModRef; + } + mod = new Module(); + mod.Name = name; + mod.Kind = ModuleKindFlags.UnmanagedDynamicallyLinkedLibrary; + if (System.IO.File.Exists(location)) mod.Location = location; + mod.ContainingAssembly = module.ContainingAssembly; + modRefs[i].Module = mod; + modules.Add(new ModuleReference(name, mod)); + nextModRef: ; + } + } + private static string ReadSerString(MemoryCursor/*!*/ sigReader) + { + int n = sigReader.ReadCompressedInt(); + if (n < 0) return null; + return sigReader.ReadUTF8(n); + } + private void AddFieldsToType(TypeNode/*!*/ type, FieldRow[]/*!*/ fieldDefs, FieldPtrRow[]/*!*/ fieldPtrs, int start, int end) + { + for (int i = start; i < end; i++) + { + int ii = i; + if (fieldPtrs.Length > 0) ii = fieldPtrs[i - 1].Field; + Field field = this.GetFieldFromDef(ii, type); + if (field != null) type.Members.Add(field); + } + } + private void GetUnderlyingTypeOfEnumNode(EnumNode /*!*/enumNode, FieldRow[]/*!*/ fieldDefs, FieldPtrRow[]/*!*/ fieldPtrs, int start, int end) + { + TypeNode underlyingType = null; + for (int i = start; i < end; i++) + { + int ii = i; + if (fieldPtrs.Length > 0) ii = fieldPtrs[i - 1].Field; + FieldRow fld = fieldDefs[ii - 1]; + if (fld.Field != null && !fld.Field.IsStatic) + { + underlyingType = fld.Field.Type; + break; + } + FieldFlags fieldFlags = (FieldFlags)fld.Flags; + if ((fieldFlags & FieldFlags.Static) == 0) + { + this.tables.GetSignatureLength(fld.Signature); + MemoryCursor sigReader = this.tables.GetNewCursor(); + GetAndCheckSignatureToken(6, sigReader); + underlyingType = this.ParseTypeSignature(sigReader); + break; + } + } + enumNode.underlyingType = underlyingType; + } + private void AddMethodsToType(TypeNode/*!*/ type, MethodPtrRow[]/*!*/ methodPtrs, int start, int end) + //^ requires type.members != null; + { + for (int i = start; i < end; i++) + { + int ii = i; + if (methodPtrs.Length > 0) ii = methodPtrs[i - 1].Method; + Method method = this.GetMethodFromDef(ii, type); + if (method != null && ((method.Flags & MethodFlags.RTSpecialName) == 0 || method.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)) + type.members.Add(method); + } + } + private void AddMoreStuffToParameters(Method method, ParameterList parameters, int start, int end) + { + ParamRow[] pars = this.tables.ParamTable; + int n = parameters == null ? 0 : parameters.Count; + for (int i = start; i < end; i++) + { + ParamRow pr = pars[i - 1]; + if (pr.Sequence == 0 && method != null) + { + //The parameter entry with sequence 0 is used as a target for custom attributes that apply to the return value + method.ReturnAttributes = this.GetCustomAttributesFor((i << 5) | 4); + if ((pr.Flags & (int)ParameterFlags.HasFieldMarshal) != 0) + method.ReturnTypeMarshallingInformation = this.GetMarshallingInformation((i << 1) | 1); + this.AddMoreStuffToParameters(null, parameters, start + 1, end); + return; + } + int j = pr.Sequence; + if (j < 1 || j > n) continue; //Bad metadata, ignore + if (parameters == null) continue; + Parameter par = parameters[j - 1]; + par.Attributes = this.GetCustomAttributesFor((i << 5) | 4); + par.Flags = (ParameterFlags)pr.Flags; + if ((par.Flags & ParameterFlags.HasDefault) != 0) + par.DefaultValue = this.GetLiteral((i << 2) | 1, par.Type); + if ((par.Flags & ParameterFlags.HasFieldMarshal) != 0) + par.MarshallingInformation = this.GetMarshallingInformation((i << 1) | 1); + par.Name = tables.GetIdentifier(pr.Name); +#if ExtendedRuntime + for (int k = 0, al = par.Attributes == null ? 0 : par.Attributes.Count; k < al; k++) { + if (par.Attributes[k].Type == ExtendedRuntimeTypes.NotNullAttribute) { + Reference r = par.Type as Reference; + if (r != null){ + // need to make it a reference to a non-null type and not a non-null wrapper around the reference + // also *must* make it a new Reference. + OptionalModifier om = OptionalModifier.For(ExtendedRuntimeTypes.NonNullType, r.ElementType); + par.Type = om.GetReferenceType(); + }else{ + par.Type = OptionalModifier.For(ExtendedRuntimeTypes.NonNullType, par.Type); + } + // Someone putting an attribute directly on the "real" method is still a + // kind of out-of-band contract. + // This marking is the way to signal that any override or implementing method being compiled + // should not have its non-null annotations persisted as optional modifiers. + par.DeclaringMethod.HasOutOfBandContract = true; + break; + } + } +#endif + } + } + private void AddPropertiesToType(TypeNode/*!*/ type, PropertyRow[]/*!*/ propertyDefs, PropertyPtrRow[]/*!*/ propertyPtrs, int start, int end) + //requires type.members != null; + { + MetadataReader tables = this.tables; + for (int i = start; i < end; i++) + { + int ii = i; + if (propertyPtrs.Length > 0) ii = propertyPtrs[i - 1].Property; + PropertyRow prop = propertyDefs[ii - 1]; + Property property = new Property(); + property.Attributes = this.GetCustomAttributesFor((ii << 5) | 9); + property.DeclaringType = type; + property.Flags = (PropertyFlags)prop.Flags; + property.Name = tables.GetIdentifier(prop.Name); + if ((property.Flags & PropertyFlags.RTSpecialName) == 0 || property.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey) + { + this.AddMethodsToProperty(ii, property); + type.members.Add(property); + } + //REVIEW: the signature seems to be redundant. Is there any point in retrieving it? + } + } + private void AddMethodsToProperty(int propIndex, Property/*!*/ property) + { + int codedPropIndex = (propIndex << 1) | 1; + MetadataReader tables = this.tables; + MethodRow[] methods = tables.MethodTable; + MethodSemanticsRow[] methodSemantics = tables.MethodSemanticsTable; + int i = 0, n = methodSemantics.Length, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodSemantics) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (methodSemantics[k].Association < codedPropIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && methodSemantics[i - 1].Association == codedPropIndex) i--; + } + for (; i < n; i++) + { + MethodSemanticsRow meth = methodSemantics[i]; + Method propertyMethod = methods[meth.Method - 1].Method; + if (propertyMethod == null) continue; + if (meth.Association == codedPropIndex) + { + propertyMethod.DeclaringMember = property; + switch (meth.Semantics) + { + case 0x0001: property.Setter = propertyMethod; break; + case 0x0002: property.Getter = propertyMethod; break; + default: + if (property.OtherMethods == null) property.OtherMethods = new MethodList(); + property.OtherMethods.Add(propertyMethod); break; + } + } + else if (sorted) + break; + } + } + private void AddEventsToType(TypeNode/*!*/ type, EventRow[]/*!*/ eventDefs, EventPtrRow[]/*!*/ eventPtrs, int start, int end) + { + MetadataReader tables = this.tables; + for (int i = start; i < end; i++) + { + int ii = i; + if (eventPtrs.Length > 0) ii = eventPtrs[i].Event; + EventRow ev = eventDefs[ii - 1]; + Event evnt = new Event(); + evnt.Attributes = this.GetCustomAttributesFor((ii << 5) | 10); + evnt.DeclaringType = type; + evnt.Flags = (EventFlags)ev.Flags; + evnt.HandlerType = this.DecodeAndGetTypeDefOrRefOrSpec(ev.EventType); + evnt.Name = tables.GetIdentifier(ev.Name); + if ((evnt.Flags & EventFlags.RTSpecialName) == 0 || evnt.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey) + { + this.AddMethodsToEvent(ii, evnt); + type.Members.Add(evnt); + } + } + } + private void AddMethodsToEvent(int eventIndex, Event/*!*/ evnt) + { + int codedEventIndex = eventIndex << 1; + MetadataReader tables = this.tables; + MethodRow[] methods = tables.MethodTable; + MethodSemanticsRow[] methodSemantics = tables.MethodSemanticsTable; + int i = 0, n = methodSemantics.Length, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodSemantics) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (methodSemantics[k].Association < codedEventIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && methodSemantics[i - 1].Association == codedEventIndex) i--; + } + MethodFlags handlerFlags = (MethodFlags)0; + for (; i < n; i++) + { + MethodSemanticsRow meth = methodSemantics[i]; + Method eventMethod = methods[meth.Method - 1].Method; + if (eventMethod == null) continue; + if (meth.Association == codedEventIndex) + { + eventMethod.DeclaringMember = evnt; + switch (meth.Semantics) + { + case 0x0008: evnt.HandlerAdder = eventMethod; handlerFlags = eventMethod.Flags; break; + case 0x0010: evnt.HandlerRemover = eventMethod; handlerFlags = eventMethod.Flags; break; + case 0x0020: evnt.HandlerCaller = eventMethod; break; + default: + if (evnt.OtherMethods == null) evnt.OtherMethods = new MethodList(); + evnt.OtherMethods.Add(eventMethod); break; + } + } + else if (sorted) + break; + } + evnt.HandlerFlags = handlerFlags; + } + private bool TypeDefOrRefOrSpecIsClass(int codedIndex) + { + if (codedIndex == 0) return false; + switch (codedIndex & 0x3) + { + case 0x00: return this.TypeDefIsClass(codedIndex >> 2); + case 0x01: TypeNode t = this.GetTypeFromRef(codedIndex >> 2); return t is Class; + case 0x02: return this.TypeSpecIsClass(codedIndex >> 2); + } + throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef); + } + private bool TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(int codedIndex) + { + if (codedIndex == 0) return false; + switch (codedIndex & 0x3) + { + case 0x00: return this.TypeDefIsClassButNotValueTypeBaseClass(codedIndex >> 2); + case 0x01: + TypeNode t = this.GetTypeFromRef(codedIndex >> 2); + return t != CoreSystemTypes.ValueType && t != CoreSystemTypes.Enum && t is Class; + case 0x02: return this.TypeSpecIsClass(codedIndex >> 2); + } + throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef); + } + private TypeNode DecodeAndGetTypeDefOrRefOrSpec(int codedIndex) + { + if (codedIndex == 0) return null; + switch (codedIndex & 0x3) + { + case 0x00: return this.GetTypeFromDef(codedIndex >> 2); + case 0x01: return this.GetTypeFromRef(codedIndex >> 2); + case 0x02: return this.GetTypeFromSpec(codedIndex >> 2); + } + throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef); + } + private TypeNode DecodeAndGetTypeDefOrRefOrSpec(int codedIndex, bool expectStruct) + { + if (codedIndex == 0) return null; + switch (codedIndex & 0x3) + { + case 0x00: return this.GetTypeFromDef(codedIndex >> 2); + case 0x01: return this.GetTypeFromRef(codedIndex >> 2, expectStruct); + case 0x02: return this.GetTypeFromSpec(codedIndex >> 2); + } + throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef); + } +#if ExtendedRuntime + private Interface GetInterfaceIfNotGenericInstance(int codedIndex){ + if (codedIndex == 0) return null; + switch(codedIndex & 0x3){ + case 0x00 : return this.GetTypeFromDef(codedIndex >> 2) as Interface; + case 0x01 : return this.GetTypeFromRef(codedIndex >> 2, false) as Interface; + } + return null; + } +#endif + private TypeNode GetTypeIfNotGenericInstance(int codedIndex) + { + if (codedIndex == 0) return null; + switch (codedIndex & 0x3) + { + case 0x00: return this.GetTypeFromDef(codedIndex >> 2); + case 0x01: return this.GetTypeFromRef(codedIndex >> 2, false); + } + return null; + } + internal AssemblyNode/*!*/ GetAssemblyFromReference(AssemblyReference/*!*/ assemblyReference) + { + lock (this) + { + if (SystemAssemblyLocation.ParsedAssembly != null && (assemblyReference.Name == "mscorlib" || assemblyReference.Name == "basetypes" || assemblyReference.Name == "ioconfig" + || assemblyReference.Name == "singularity.v1")) + return SystemAssemblyLocation.ParsedAssembly; + if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assemblyReference.Name) return CoreSystemTypes.SystemAssembly; + string strongName = null; + object cachedValue = null; + if (assemblyReference.PublicKeyOrToken == null || assemblyReference.PublicKeyOrToken.Length == 0) + { + if (assemblyReference.Location != null) + cachedValue = this.localAssemblyCache[assemblyReference.Location]; + if (cachedValue == null) + { + cachedValue = this.localAssemblyCache[assemblyReference.Name]; + if (cachedValue != null && assemblyReference.Location != null) + this.localAssemblyCache[assemblyReference.Location] = cachedValue; + } + } + else + { + strongName = assemblyReference.StrongName; + if (this.useStaticCache) + { + //See if reference is to an assembly that lives in the GAC. + if (assemblyReference.Location != null) + cachedValue = Reader.StaticAssemblyCache[assemblyReference.Location]; + if (cachedValue == null) + cachedValue = Reader.StaticAssemblyCache[strongName]; + } + if (cachedValue == null) + cachedValue = this.localAssemblyCache[strongName]; + } + if (cachedValue == null) + { + //See if assembly is a platform assembly (and apply unification) + AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(assemblyReference.Name).UniqueIdKey]; + if (aRef != null && assemblyReference.Version != null && aRef.Version >= assemblyReference.Version && aRef.MatchesIgnoringVersion(assemblyReference)) + { + AssemblyNode platformAssembly = aRef.assembly; + if (platformAssembly == null) + { + Debug.Assert(aRef.Location != null); + platformAssembly = AssemblyNode.GetAssembly(aRef.Location, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + } + if (platformAssembly != null) + { + if (strongName == null) strongName = assemblyReference.Name; + lock (Reader.StaticAssemblyCache) + { + if (aRef.Location != null) + Reader.StaticAssemblyCache[aRef.Location] = platformAssembly; + Reader.StaticAssemblyCache[strongName] = platformAssembly; + } + return aRef.assembly = platformAssembly; + } + } + } + AssemblyNode assembly = cachedValue as AssemblyNode; + if (assembly != null) goto done; + + //No cached assembly and no cached reader for this assembly. Look for a resolver. + if (this.module != null) + { + assembly = this.module.Resolve(assemblyReference); + if (assembly != null) + { + if (strongName == null) + { + this.localAssemblyCache[assembly.Name] = assembly; + if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly; + } + else + { + if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assembly.Name) return CoreSystemTypes.SystemAssembly; + lock (Reader.StaticAssemblyCache) + { + if (this.useStaticCache) + { + if (assembly.Location != null) + Reader.StaticAssemblyCache[assembly.Location] = assembly; + Reader.StaticAssemblyCache[strongName] = assembly; + } + else + { + this.localAssemblyCache[strongName] = assembly; + if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly; + } + } + } + goto done; + } + } + + //Look for an assembly with the given name in the same directory as the referencing module + if (this.directory != null) + { + string fileName = System.IO.Path.Combine(this.directory, assemblyReference.Name + ".dll"); + if (System.IO.File.Exists(fileName)) + { + assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + if (assembly != null) + { + if (strongName == null) goto cacheIt; //found something + //return assembly only if it matches the strong name of the reference + if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt; + } + } + fileName = System.IO.Path.Combine(this.directory, assemblyReference.Name + ".exe"); + if (System.IO.File.Exists(fileName)) + { + assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + if (assembly != null) + { + if (strongName == null) goto cacheIt; //found something + //return assembly only if it matches the strong name of the reference + if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt; + } + } + fileName = System.IO.Path.Combine(this.directory, assemblyReference.Name + ".ill"); + if (System.IO.File.Exists(fileName)) + { + assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + if (assembly != null) + { + if (strongName == null) goto cacheIt; //found something + //return assembly only if it matches the strong name of the reference + if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt; + } + } + } + //Look for an assembly in the same directory as the application using Reader. + { + string fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyReference.Name + ".dll"); + if (System.IO.File.Exists(fileName)) + { + assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + if (assembly != null) + { + if (strongName == null) goto cacheIt; //found something + //return assembly only if it matches the strong name of the reference + if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt; + } + } + fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyReference.Name + ".exe"); + if (System.IO.File.Exists(fileName)) + { + assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + if (assembly != null) + { + if (strongName == null) goto cacheIt; //found something + //return assembly only if it matches the strong name of the reference + if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt; + } + } + } + assembly = null; + + //Probe the GAC +#if FxCop + if(probeGAC){ +#endif + string gacLocation = null; + if (strongName != null) + { +#if !ROTOR + //Look for the assembly in the system's Global Assembly Cache + gacLocation = GlobalAssemblyCache.GetLocation(assemblyReference); + if (gacLocation != null && gacLocation.Length == 0) gacLocation = null; +#else + //TODO: look in the ROTOR GAC +#endif + if (gacLocation != null) + { + assembly = AssemblyNode.GetAssembly(gacLocation, this.useStaticCache ? Reader.StaticAssemblyCache : this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache); + if (assembly != null) + { + lock (Reader.StaticAssemblyCache) + { + if (this.useStaticCache) + { + Reader.StaticAssemblyCache[gacLocation] = assembly; + Reader.StaticAssemblyCache[strongName] = assembly; + } + else + { + this.localAssemblyCache[gacLocation] = assembly; + this.localAssemblyCache[strongName] = assembly; + } + } + } + } + } +#if FxCop + } +#endif + goto done; + cacheIt: + if (strongName == null) + { + this.localAssemblyCache[assembly.Name] = assembly; + if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly; + } + else + { + this.localAssemblyCache[strongName] = assembly; + if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly; + } + done: + if (assembly != null) + assembly.InitializeAssemblyReferenceResolution(this.module); + if (assembly == null) + { + if (this.module != null) + { + assembly = this.module.ResolveAfterProbingFailed(assemblyReference); + if (assembly != null) goto cacheIt; + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.AssemblyReferenceNotResolved, assemblyReference.StrongName)); + } + assembly = new AssemblyNode(); + assembly.Culture = assemblyReference.Culture; + assembly.Name = assemblyReference.Name; + assembly.PublicKeyOrToken = assemblyReference.PublicKeyOrToken; + assembly.Version = assemblyReference.Version; + assembly.Location = "unknown:location"; + goto cacheIt; + } + return assembly; + } + } + private static void GetAndCheckSignatureToken(int expectedToken, MemoryCursor/*!*/ sigReader) + { + int tok = sigReader.ReadCompressedInt(); + if (tok != expectedToken) throw new InvalidMetadataException(ExceptionStrings.MalformedSignature); + } + private Method GetConstructorDefOrRef(int codedIndex, out TypeNodeList varArgTypes) + { + varArgTypes = null; + switch (codedIndex & 0x7) + { + case 0x02: return this.GetMethodFromDef(codedIndex >> 3); + case 0x03: return (Method)this.GetMemberFromRef(codedIndex >> 3, out varArgTypes); + } + throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken); + } + private void GetResources(Module/*!*/ module) + { + ManifestResourceRow[] manifestResourceTable = this.tables.ManifestResourceTable; + int n = manifestResourceTable.Length; + ResourceList resources = new ResourceList(n); + for (int i = 0; i < n; i++) + { + ManifestResourceRow mrr = manifestResourceTable[i]; + Resource r = new Resource(); + r.Name = this.tables.GetString(mrr.Name); + r.IsPublic = (mrr.Flags & 7) == 1; + int impl = mrr.Implementation; + if (impl != 0) + { + switch (impl & 0x3) + { + case 0x0: + string modName = this.tables.GetString(this.tables.FileTable[(impl >> 2) - 1].Name); + if ((this.tables.FileTable[(impl >> 2) - 1].Flags & (int)FileFlags.ContainsNoMetaData) != 0) + { + r.DefiningModule = new Module(); + r.DefiningModule.Directory = module.Directory; + r.DefiningModule.Location = Path.Combine(module.Directory, modName); + r.DefiningModule.Name = modName; + r.DefiningModule.Kind = ModuleKindFlags.ManifestResourceFile; + r.DefiningModule.ContainingAssembly = module.ContainingAssembly; + r.DefiningModule.HashValue = this.tables.GetBlob(this.tables.FileTable[(impl >> 2) - 1].HashValue); + } + else + { + string modLocation = modName; + r.DefiningModule = GetNestedModule(module, modName, ref modLocation); + } + break; + case 0x1: + r.DefiningModule = this.tables.AssemblyRefTable[(impl >> 2) - 1].AssemblyReference.Assembly; + break; + } + } + else + { + r.DefiningModule = module; + r.Data = this.tables.GetResourceData(mrr.Offset); + } + resources.Add(r); + } + module.Resources = resources; + module.Win32Resources = this.tables.ReadWin32Resources(); + } + private SecurityAttribute GetSecurityAttribute(int i) + { + DeclSecurityRow dsr = this.tables.DeclSecurityTable[i]; + SecurityAttribute attr = new SecurityAttribute(); + attr.Action = (System.Security.Permissions.SecurityAction)dsr.Action; + if (this.module.MetadataFormatMajorVersion > 1 || this.module.MetadataFormatMinorVersion > 0) + { + attr.PermissionAttributes = this.GetPermissionAttributes(dsr.PermissionSet, attr.Action); + if (attr.PermissionAttributes != null) return attr; + } + attr.SerializedPermissions = (string)this.tables.GetBlobString(dsr.PermissionSet); + return attr; + } + private AttributeList GetPermissionAttributes(int blobIndex, System.Security.Permissions.SecurityAction action) + { + AttributeList result = new AttributeList(); + int blobLength; + MemoryCursor sigReader = this.tables.GetBlobCursor(blobIndex, out blobLength); + if (blobLength == 0) return null; + byte header = sigReader.ReadByte(); + if (header != (byte)'*') + { + if (header == (byte)'<') return null; + if (header == (byte)'.') return this.GetPermissionAttributes2(blobIndex, action); + HandleError(this.module, ExceptionStrings.BadSecurityPermissionSetBlob); + return null; + } + sigReader.ReadInt32(); //Skip over the token for the attribute target + sigReader.ReadInt32(); //Skip over the security action + int numAttrs = sigReader.ReadInt32(); + for (int i = 0; i < numAttrs; i++) + result.Add(this.GetPermissionAttribute(sigReader)); + return result; + } + private AttributeNode GetPermissionAttribute(MemoryCursor/*!*/ sigReader) + { + sigReader.ReadInt32(); //Skip over index + int typeNameLength = sigReader.ReadInt32(); + sigReader.ReadUTF8(typeNameLength); //Skip over type name + int constructorToken = sigReader.ReadInt32(); + sigReader.ReadInt32(); //Skip over attribute type token + sigReader.ReadInt32(); //Skip over assembly ref token + int caBlobLength = sigReader.ReadInt32(); + sigReader.ReadInt32(); //Skip over the number of parameters in the CA blob + TypeNodeList varArgTypes; //Ignored because vararg constructors are not allowed in Custom Attributes + Method cons = this.GetConstructorDefOrRef(constructorToken, out varArgTypes); + if (cons == null) cons = new Method(); + return this.GetCustomAttribute(cons, sigReader, caBlobLength); + } + private AttributeList GetPermissionAttributes2(int blobIndex, System.Security.Permissions.SecurityAction action) + { + AttributeList result = new AttributeList(); + int blobLength; + MemoryCursor sigReader = this.tables.GetBlobCursor(blobIndex, out blobLength); + if (blobLength == 0) return null; + byte header = sigReader.ReadByte(); + if (header != (byte)'.') + { + HandleError(this.module, ExceptionStrings.BadSecurityPermissionSetBlob); + return null; + } + int numAttrs = sigReader.ReadCompressedInt(); + for (int i = 0; i < numAttrs; i++) + result.Add(this.GetPermissionAttribute2(sigReader, action)); + return result; + } + private AttributeNode GetPermissionAttribute2(MemoryCursor/*!*/ sigReader, System.Security.Permissions.SecurityAction action) + { + int typeNameLength = sigReader.ReadCompressedInt(); + string serializedTypeName = sigReader.ReadUTF8(typeNameLength); + TypeNode attrType = null; + try + { + attrType = this.GetTypeFromSerializedName(serializedTypeName); + } + catch (InvalidMetadataException) { } + if (attrType == null) + { + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.CouldNotResolveType, serializedTypeName)); + return null; + } + InstanceInitializer cons = attrType.GetConstructor(CoreSystemTypes.SecurityAction); + if (cons == null) + { + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.SecurityAttributeTypeDoesNotHaveADefaultConstructor, serializedTypeName)); + return null; + } + sigReader.ReadCompressedInt(); //caBlobLength + int numProps = sigReader.ReadCompressedInt(); //Skip over the number of properties in the CA blob + ExpressionList arguments = new ExpressionList(numProps + 1); + arguments.Add(new Literal(action, CoreSystemTypes.SecurityAction)); + this.GetCustomAttributeNamedArguments(arguments, (ushort)numProps, sigReader); + return new AttributeNode(new MemberBinding(null, cons), arguments); + } + private static void HandleError(Module mod, string errorMessage) + { +#if !FxCop + if (mod != null) + { + if (mod.MetadataImportErrors == null) mod.MetadataImportErrors = new ArrayList(); + mod.MetadataImportErrors.Add(new InvalidMetadataException(errorMessage)); + } +#else + throw new InvalidMetadataException(String.Format(CultureInfo.CurrentCulture, ExceptionStrings.ModuleError, mod.Name, errorMessage)); +#endif + } + private AttributeNode GetCustomAttribute(int i) + { + CustomAttributeRow ca = this.tables.CustomAttributeTable[i]; + TypeNodeList varArgTypes; //Ignored because vararg constructors are not allowed in Custom Attributes + Method cons = this.GetConstructorDefOrRef(ca.Constructor, out varArgTypes); + if (cons == null) cons = new Method(); + int blobLength; + MemoryCursor sigReader = this.tables.GetBlobCursor(ca.Value, out blobLength); + return this.GetCustomAttribute(cons, sigReader, blobLength); + } + private AttributeNode GetCustomAttribute(Method/*!*/ cons, MemoryCursor/*!*/ sigReader, int blobLength) + { + AttributeNode attr = new AttributeNode(); + attr.Constructor = new MemberBinding(null, cons); + int n = cons.Parameters == null ? 0 : cons.Parameters.Count; + ExpressionList arguments = attr.Expressions = new ExpressionList(n); + int posAtBlobStart = sigReader.Position; + sigReader.ReadUInt16(); //Prolog + for (int j = 0; j < n; j++) + { + TypeNode t = TypeNode.StripModifiers(cons.Parameters[j].Type); + if (t == null) continue; + TypeNode/*!*/ pt = t; + object val = null; + try + { + val = this.GetCustomAttributeLiteralValue(sigReader, ref pt); +#if !FxCop + } + catch (Exception e) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } +#else + }finally{} +#endif + Literal lit = val as Literal; + if (lit == null) lit = new Literal(val, pt); + arguments.Add(lit); + } + if (sigReader.Position + 1 < posAtBlobStart + blobLength) + { + ushort numNamed = sigReader.ReadUInt16(); + this.GetCustomAttributeNamedArguments(arguments, numNamed, sigReader); + } + return attr; + } + private void GetCustomAttributeNamedArguments(ExpressionList/*!*/ arguments, ushort numNamed, MemoryCursor/*!*/ sigReader) + { + for (int j = 0; j < numNamed; j++) + { + int nameTag = sigReader.ReadByte(); + bool mustBox = sigReader.Byte(0) == (byte)ElementType.BoxedEnum; + TypeNode/*!*/ vType = this.ParseTypeSignature(sigReader); + Identifier id = sigReader.ReadIdentifierFromSerString(); + object val = this.GetCustomAttributeLiteralValue(sigReader, ref vType); + Literal lit = val as Literal; + if (lit == null) lit = new Literal(val, vType); + NamedArgument narg = new NamedArgument(id, lit); + narg.Type = vType; + narg.IsCustomAttributeProperty = nameTag == 0x54; + narg.ValueIsBoxed = mustBox; + arguments.Add(narg); + } + } + private object GetCustomAttributeLiteralValue(MemoryCursor/*!*/ sigReader, TypeNode/*!*/ type) + { + TypeNode/*!*/ t = type; + object result = this.GetCustomAttributeLiteralValue(sigReader, ref t); + EnumNode enumType = t as EnumNode; + if (enumType != null && type == CoreSystemTypes.Object) result = new Literal(result, enumType); + return result; + } + private object GetCustomAttributeLiteralValue(MemoryCursor/*!*/ sigReader, ref TypeNode/*!*/ type) + { + if (type == null) return sigReader.ReadInt32(); + switch (type.typeCode) + { + case ElementType.Boolean: return sigReader.ReadBoolean(); + case ElementType.Char: return sigReader.ReadChar(); + case ElementType.Double: return sigReader.ReadDouble(); + case ElementType.Single: return sigReader.ReadSingle(); + case ElementType.Int16: return sigReader.ReadInt16(); + case ElementType.Int32: return sigReader.ReadInt32(); + case ElementType.Int64: return sigReader.ReadInt64(); + case ElementType.Int8: return sigReader.ReadSByte(); + case ElementType.UInt16: return sigReader.ReadUInt16(); + case ElementType.UInt32: return sigReader.ReadUInt32(); + case ElementType.UInt64: return sigReader.ReadUInt64(); + case ElementType.UInt8: return sigReader.ReadByte(); + case ElementType.String: return ReadSerString(sigReader); + case ElementType.ValueType: + EnumNode etype = GetCustomAttributeEnumNode(ref type); + return this.GetCustomAttributeLiteralValue(sigReader, etype.UnderlyingType); + case ElementType.Class: return this.GetTypeFromSerializedName(ReadSerString(sigReader)); + case ElementType.SzArray: + int numElems = sigReader.ReadInt32(); + TypeNode elemType = ((ArrayType)type).ElementType; + return this.GetCustomAttributeLiteralArray(sigReader, numElems, elemType); + case ElementType.Object: + { + type = this.ParseTypeSignature(sigReader); + return this.GetCustomAttributeLiteralValue(sigReader, ref type); + } + } + throw new InvalidMetadataException(ExceptionStrings.UnexpectedTypeInCustomAttribute); + } + private static EnumNode/*!*/ GetCustomAttributeEnumNode(ref TypeNode/*!*/ type) + { + EnumNode etype = ((TypeNode)type) as EnumNode; + if (etype == null || etype.UnderlyingType == null) + { + //Happens when type is declared in a assembly that has not been resolved. In that case only the type name + //and the fact that it is a value type is known. There is no completely safe recovery from it, but at this point we + //can fake up an enum with Int32 as underlying type. This works in most situations. + etype = new EnumNode(); + etype.Name = type.Name; + etype.Namespace = type.Namespace; + etype.DeclaringModule = type.DeclaringModule; + etype.UnderlyingType = CoreSystemTypes.Int32; + type = etype; + } + return etype; + } + private Array GetCustomAttributeLiteralArray(MemoryCursor/*!*/ sigReader, int numElems, TypeNode/*!*/ elemType) + { + Array array = this.ConstructCustomAttributeLiteralArray(numElems, elemType); + for (int i = 0; i < numElems; i++) + { + object elem = this.GetCustomAttributeLiteralValue(sigReader, elemType); + array.SetValue(elem, i); + } + return array; + } + private Array ConstructCustomAttributeLiteralArray(int numElems, TypeNode/*!*/ elemType) + { + if (numElems == -1) return null; + if (numElems < 0) throw new InvalidMetadataException(ExceptionStrings.UnexpectedTypeInCustomAttribute); + switch (elemType.typeCode) + { + case ElementType.Boolean: return new Boolean[numElems]; + case ElementType.Char: return new Char[numElems]; + case ElementType.Double: return new Double[numElems]; + case ElementType.Single: return new Single[numElems]; + case ElementType.Int16: return new Int16[numElems]; + case ElementType.Int32: return new Int32[numElems]; + case ElementType.Int64: return new Int64[numElems]; + case ElementType.Int8: return new SByte[numElems]; + case ElementType.UInt16: return new UInt16[numElems]; + case ElementType.UInt32: return new UInt32[numElems]; + case ElementType.UInt64: return new UInt64[numElems]; + case ElementType.UInt8: return new Byte[numElems]; + case ElementType.String: return new String[numElems]; + // Only enum value types are legal in attribute instances as stated in section 17.1.3 of the C# 1.0 spec + case ElementType.ValueType: + TypeNode/*!*/ elType = elemType; + EnumNode eType = GetCustomAttributeEnumNode(ref elType); + return this.ConstructCustomAttributeLiteralArray(numElems, eType.UnderlyingType); + // This needs to be a TypeNode since GetCustomAttributeLiteralValue will return a Struct if the Type is a value type + case ElementType.Class: return new TypeNode[numElems]; + // REVIEW: Is this the right exception? Is this the right exception string? + // Multi-dimensional arrays are not legal in attribute instances according section 17.1.3 of the C# 1.0 spec + case ElementType.SzArray: throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken); + case ElementType.Object: return new Object[numElems]; + } + throw new InvalidMetadataException(ExceptionStrings.UnexpectedTypeInCustomAttribute); + } + //TODO: rewrite this entire mess using a proper grammar based parser + private TypeNode/*!*/ GetTypeFromSerializedName(string serializedName) + { + if (serializedName == null) return null; + string assemblyName = null; + string typeName = serializedName; + int firstComma = FindFirstCommaOutsideBrackets(serializedName); + if (firstComma > 0) + { + int i = 1; + while (firstComma + i < serializedName.Length && serializedName[firstComma + i] == ' ') i++; + assemblyName = serializedName.Substring(firstComma + i); + typeName = serializedName.Substring(0, firstComma); + } + return this.GetTypeFromSerializedName(typeName, assemblyName); + } + private static int FindFirstCommaOutsideBrackets(string/*!*/ serializedName) + { + int numBrackets = 0; + int numAngles = 0; + for (int i = 0, n = serializedName == null ? 0 : serializedName.Length; i < n; i++) + { + char ch = serializedName[i]; + if (ch == '[') + numBrackets++; + else if (ch == ']') + { + if (--numBrackets < 0) return -1; + } + else if (ch == '<') + numAngles++; + else if (ch == '>') + { + if (--numAngles < 0) return -1; + } + else if (ch == ',' && numBrackets == 0 && numAngles == 0) + return i; + } + return -1; + } + private TypeNode/*!*/ GetTypeFromSerializedName(string/*!*/ typeName, string assemblyName) + { + string/*!*/ nspace, name; + int i; + ParseTypeName(typeName, out nspace, out name, out i); + Module tMod = null; + TypeNode t = this.LookupType(nspace, name, assemblyName, out tMod); + if (t == null) + { + if (i < typeName.Length && typeName[i] == '!') + { + int codedIndex = 0; + if (PlatformHelpers.TryParseInt32(typeName.Substring(0, i), out codedIndex)) + { + t = this.DecodeAndGetTypeDefOrRefOrSpec(codedIndex); + if (t != null) return t; + } + } + t = this.GetDummyTypeNode(Identifier.For(nspace), Identifier.For(name), tMod, null, false); + } + if (i >= typeName.Length) return t; + char ch = typeName[i]; + if (ch == '+') return this.GetTypeFromSerializedName(typeName.Substring(i + 1), t); + if (ch == '&') return t.GetReferenceType(); + if (ch == '*') return t.GetPointerType(); + if (ch == '[') return this.ParseArrayOrGenericType(typeName.Substring(i + 1, typeName.Length - 1 - i), t); + throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); + } + private TypeNode/*!*/ GetTypeFromSerializedName(string/*!*/ typeName, TypeNode/*!*/ nestingType) + { + string/*!*/ name; + int i = 0; + ParseSimpleTypeName(typeName, out name, ref i); + TypeNode t = nestingType.GetNestedType(Identifier.For(name)); + if (t == null) + t = this.GetDummyTypeNode(Identifier.Empty, Identifier.For(name), nestingType.DeclaringModule, nestingType, false); + if (i >= typeName.Length) return t; + char ch = typeName[i]; + if (ch == '+') return this.GetTypeFromSerializedName(typeName.Substring(i + 1), t); + if (ch == '&') return t.GetReferenceType(); + if (ch == '*') return t.GetPointerType(); + if (ch == '[') return this.ParseArrayOrGenericType(typeName.Substring(i + 1, typeName.Length - 1 - i), t); + throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); + } + private TypeNode/*!*/ ParseArrayOrGenericType(string typeName, TypeNode/*!*/ rootType) + { + if (typeName == null || rootType == null) { Debug.Assert(false); return rootType; } + //Get here after "rootType[" has been parsed. What follows is either an array type specifier or some generic type arguments. + if (typeName.Length == 0) + throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); //Something ought to follow the [ + if (typeName[0] == ']') + { //Single dimensional array with zero lower bound + if (typeName.Length == 1) return rootType.GetArrayType(1); + if (typeName[1] == '[' && typeName.Length > 2) + return this.ParseArrayOrGenericType(typeName.Substring(2), rootType.GetArrayType(1)); + throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); + } + if (typeName[0] == '*') + { //Single dimensional array with unknown lower bound + if (typeName.Length > 1 && typeName[1] == ']') + { + if (typeName.Length == 2) return rootType.GetArrayType(1, true); + if (typeName[2] == '[' && typeName.Length > 3) + return this.ParseArrayOrGenericType(typeName.Substring(3), rootType.GetArrayType(1, true)); + } + throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); + } + if (typeName[0] == ',') + { //Muti dimensional array + int rank = 1; + while (rank < typeName.Length && typeName[rank] == ',') rank++; + if (rank < typeName.Length && typeName[rank] == ']') + { + if (typeName.Length == rank + 1) return rootType.GetArrayType(rank + 1); + if (typeName[rank + 1] == '[' && typeName.Length > rank + 2) + return this.ParseArrayOrGenericType(typeName.Substring(rank + 2), rootType.GetArrayType(rank)); + } + throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); + } + //Generic type instance + int offset = 0; + if (typeName[0] == '[') offset = 1; //Assembly qualified type name forming part of a generic parameter list + TypeNodeList arguments = new TypeNodeList(); + int commaPos = FindFirstCommaOutsideBrackets(typeName); + while (commaPos > 1) + { + arguments.Add(this.GetTypeFromSerializedName(typeName.Substring(offset, commaPos - offset))); + typeName = typeName.Substring(commaPos + 1); + offset = typeName[0] == '[' ? 1 : 0; + commaPos = FindFirstCommaOutsideBrackets(typeName); + } + //Find the position of the first unbalanced ]. + int lastCharPos = offset; + for (int leftBracketCount = 0; lastCharPos < typeName.Length; lastCharPos++) + { + char ch = typeName[lastCharPos]; + if (ch == '[') leftBracketCount++; + else if (ch == ']') + { + leftBracketCount--; + if (leftBracketCount < 0) break; + } + } + arguments.Add(this.GetTypeFromSerializedName(typeName.Substring(offset, lastCharPos - offset))); + TypeNode retVal = rootType.GetGenericTemplateInstance(this.module, arguments); + if (lastCharPos + 1 < typeName.Length && typeName[lastCharPos + 1] == ']') + lastCharPos++; + if (lastCharPos + 1 < typeName.Length) + { + //The generic type is complete, but there is yet more to the type + char ch = typeName[lastCharPos + 1]; + if (ch == '+') retVal = this.GetTypeFromSerializedName(typeName.Substring(lastCharPos + 2), retVal); + if (ch == '&') retVal = retVal.GetReferenceType(); + if (ch == '*') retVal = retVal.GetPointerType(); + if (ch == '[') retVal = this.ParseArrayOrGenericType(typeName.Substring(lastCharPos + 2, typeName.Length - 1 - lastCharPos - 1), retVal); + } + return retVal; + } + private static void ParseSimpleTypeName(string/*!*/ source, out string/*!*/ name, ref int i) + { + int n = source.Length; + int start = i; + for (; i < n; i++) + { + char ch = source[i]; + if (ch == '\\') { i++; continue; } + if (ch == '.' || ch == '+' || ch == '&' || ch == '*' || ch == '[' || ch == '!') break; + if (ch == '<') + { + int unmatched = 1; + while (unmatched > 0 && ++i < n) + { + ch = source[i]; + if (ch == '\\') i++; + else if (ch == '<') unmatched++; + else if (ch == '>') unmatched--; + } + } + } + if (i < n) + name = source.Substring(start, i - start); + else + name = source.Substring(start); + } + private static void ParseTypeName(string/*!*/ source, out string/*!*/ nspace, out string/*!*/ name, out int i) + { + i = 0; + int n = source.Length; + nspace = string.Empty; + while (true) + { + int start = i; + ParseSimpleTypeName(source, out name, ref i); + if (i < n && source[i] == '.') { i++; continue; } + if (start != 0) nspace = source.Substring(0, start - 1); + return; + } + } + private TypeNode LookupType(string/*!*/ nameSpace, string/*!*/ name, string assemblyName, out Module module) + { + Identifier namespaceId = Identifier.For(nameSpace); + Identifier nameId = Identifier.For(name); + module = this.module; + //^ assume module != null; + if (assemblyName == null) + { + TypeNode t = module.GetType(namespaceId, nameId); + if (t != null) return t; + module = CoreSystemTypes.SystemAssembly; + return CoreSystemTypes.SystemAssembly.GetType(namespaceId, nameId); + } + //See if the type is in one of the assemblies explcitly referenced by the current module + AssemblyReferenceList arefs = module.AssemblyReferences; + for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++) + { + AssemblyReference aref = arefs[i]; + if (aref != null && aref.StrongName == assemblyName && aref.Assembly != null) + { + module = aref.Assembly; + return aref.Assembly.GetType(namespaceId, nameId); + } + } + //Construct an assembly reference and probe for it + AssemblyReference aRef = new AssemblyReference(assemblyName); + AssemblyNode referringAssembly = this.module as AssemblyNode; + if (referringAssembly != null && (referringAssembly.Flags & AssemblyFlags.Retargetable) != 0) + aRef.Flags |= AssemblyFlags.Retargetable; + AssemblyNode aNode = this.GetAssemblyFromReference(aRef); + if (aNode != null) + { + module = aNode; + TypeNode result = aNode.GetType(namespaceId, nameId); + return result; + } + return null; + } + private void GetCustomAttributesFor(Module/*!*/ module) + { + try + { + if (this.tables.entryPointToken != 0) + module.EntryPoint = (Method)this.GetMemberFromToken(this.tables.entryPointToken); + else + module.EntryPoint = Module.NoSuchMethod; + if (module.NodeType == NodeType.Module) + { + module.Attributes = this.GetCustomAttributesFor((1 << 5) | 7); + return; + } + AssemblyNode assembly = (AssemblyNode)module; + assembly.SecurityAttributes = this.GetSecurityAttributesFor((1 << 2) | 2); + assembly.Attributes = this.GetCustomAttributesFor((1 << 5) | 14); + assembly.ModuleAttributes = this.GetCustomAttributesFor((1 << 5) | 7); +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + module.Attributes = new AttributeList(0); + } +#else + }finally{} +#endif + } + private AttributeList/*!*/ GetCustomAttributesFor(int parentIndex) + { + CustomAttributeRow[] customAttributes = this.tables.CustomAttributeTable; + AttributeList attributes = new AttributeList(); + try + { + int i = 0, n = customAttributes.Length, j = n - 1; + if (n == 0) return attributes; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.CustomAttribute) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (customAttributes[k].Parent < parentIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && customAttributes[i - 1].Parent == parentIndex) i--; + } + for (; i < n; i++) + if (customAttributes[i].Parent == parentIndex) + attributes.Add(this.GetCustomAttribute(i)); + else if (sorted) + break; +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return attributes; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } +#else + }finally{} +#endif + return attributes; + } + private SecurityAttributeList GetSecurityAttributesFor(int parentIndex) + { + DeclSecurityRow[] securityAttributes = this.tables.DeclSecurityTable; + SecurityAttributeList attributes = new SecurityAttributeList(); + try + { + int i = 0, n = securityAttributes.Length, j = n - 1; + if (n == 0) return attributes; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.DeclSecurity) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (securityAttributes[k].Parent < parentIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && securityAttributes[i - 1].Parent == parentIndex) i--; + } + for (; i < n; i++) + if (securityAttributes[i].Parent == parentIndex) + attributes.Add(this.GetSecurityAttribute(i)); + else if (sorted) + break; +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return attributes; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } +#else + }finally{} +#endif + return attributes; + } + private void GetTypeParameterConstraints(int parentIndex, TypeNodeList parameters) + { + if (parameters == null) return; + GenericParamRow[] genericParameters = this.tables.GenericParamTable; + int i = 0, n = genericParameters.Length, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParam) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (genericParameters[k].Owner < parentIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && genericParameters[i - 1].Owner == parentIndex) i--; + } + for (int k = 0; i < n && k < parameters.Count; i++, k++) + if (genericParameters[i].Owner == parentIndex) + { + TypeNode gp = parameters[k]; + this.GetGenericParameterConstraints(i, ref gp); + parameters[k] = gp; + } + else if (sorted) + break; + } + private TypeNodeList GetTypeParametersFor(int parentIndex, Member parent) + { + GenericParamRow[] genericParameters = this.tables.GenericParamTable; + TypeNodeList types = new TypeNodeList(); + int i = 0, n = genericParameters.Length, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParam) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (genericParameters[k].Owner < parentIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && genericParameters[i - 1].Owner == parentIndex) i--; + } + for (int index = 0; i < n; i++, index++) + if (genericParameters[i].Owner == parentIndex) + types.Add(this.GetGenericParameter(i, index, parent)); + else if (sorted) + break; + if (types.Count == 0) return null; + return types; + } + private TypeNode GetGenericParameter(int index, int parameterListIndex, Member parent) + { + GenericParamRow[] genericParameters = this.tables.GenericParamTable; + GenericParamRow gpr = genericParameters[index++]; + string name = this.tables.GetString(gpr.Name); + GenericParamConstraintRow[] genericParameterConstraints = this.tables.GenericParamConstraintTable; + bool isClass = false; + int i = 0, n = genericParameterConstraints.Length, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParamConstraint) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (genericParameterConstraints[k].Param < index) + i = k + 1; + else + j = k; + } + while (i > 0 && genericParameterConstraints[i - 1].Param == index) i--; + } + for (; i < n && !isClass; i++) + { + if (genericParameterConstraints[i].Param == index) + { + isClass = this.TypeDefOrRefOrSpecIsClass(genericParameterConstraints[i].Constraint); + } + else if (sorted) + break; + } + if (isClass) + { + ClassParameter cp = parent is Method ? new MethodClassParameter() : new ClassParameter(); + cp.DeclaringMember = parent; + cp.ParameterListIndex = parameterListIndex; + cp.Name = Identifier.For(name); + cp.DeclaringModule = this.module; + cp.TypeParameterFlags = (TypeParameterFlags)gpr.Flags; + return cp; + } + TypeParameter tp = parent is Method ? new MethodTypeParameter() : new TypeParameter(); + tp.DeclaringMember = parent; + tp.ParameterListIndex = parameterListIndex; + tp.Name = Identifier.For(name); + tp.DeclaringModule = this.module; + tp.TypeParameterFlags = (TypeParameterFlags)gpr.Flags; + return tp; + } + private void GetGenericParameterConstraints(int index, ref TypeNode/*!*/ parameter) + { + Debug.Assert(parameter != null); + index++; + GenericParamConstraintRow[] genericParameterConstraints = this.tables.GenericParamConstraintTable; + TypeNodeList constraints = new TypeNodeList(); + Class baseClass = null; + InterfaceList interfaces = new InterfaceList(); + int i = 0, n = genericParameterConstraints.Length, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParamConstraint) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (genericParameterConstraints[k].Param < index) + i = k + 1; + else + j = k; + } + while (i > 0 && genericParameterConstraints[i - 1].Param == index) i--; + } + for (; i < n; i++) + { + if (genericParameterConstraints[i].Param == index) + { + TypeNode t = this.DecodeAndGetTypeDefOrRefOrSpec(genericParameterConstraints[i].Constraint); + Class c = t as Class; + if (c != null) + baseClass = c; + else if (t is Interface) + interfaces.Add((Interface)t); + constraints.Add(t); + } + else if (sorted) + break; + } + ClassParameter cp = parameter as ClassParameter; + if (cp == null && baseClass != null) + { + cp = ((ITypeParameter)parameter).DeclaringMember is Method ? new MethodClassParameter() : new ClassParameter(); + cp.Name = parameter.Name; + cp.DeclaringMember = ((ITypeParameter)parameter).DeclaringMember; + cp.ParameterListIndex = ((ITypeParameter)parameter).ParameterListIndex; + cp.DeclaringModule = this.module; + cp.TypeParameterFlags = ((ITypeParameter)parameter).TypeParameterFlags; + parameter = cp; + } + if (cp != null) + cp.structuralElementTypes = constraints; + else + ((TypeParameter)parameter).structuralElementTypes = constraints; + if (baseClass != null && cp != null) cp.BaseClass = baseClass; + parameter.Interfaces = interfaces; + } + internal static Block/*!*/ GetOrCreateBlock(TrivialHashtable/*!*/ blockMap, int address) + { + Block block = (Block)blockMap[address + 1]; + if (block == null) + { + blockMap[address + 1] = block = new Block(new StatementList()); +#if !FxCop + block.SourceContext.StartPos = address; +#else + block.ILOffset = address; +#endif + } + return block; + } + internal Field GetFieldFromDef(int i) + { + return this.GetFieldFromDef(i, null); + } + internal Field GetFieldFromDef(int i, TypeNode declaringType) + { + FieldRow[] fieldDefs = this.tables.FieldTable; + FieldRow fld = fieldDefs[i - 1]; + if (fld.Field != null) return fld.Field; + Field field = new Field(); + fieldDefs[i - 1].Field = field; + field.Attributes = this.GetCustomAttributesFor((i << 5) | 1); + field.Flags = (FieldFlags)fld.Flags; + field.Name = tables.GetIdentifier(fld.Name); + if ((field.Flags & FieldFlags.RTSpecialName) != 0 && field.Name.UniqueIdKey == StandardIds._Deleted.UniqueIdKey) return null; + tables.GetSignatureLength(fld.Signature); //sigLength + MemoryCursor sigReader = this.tables.GetNewCursor(); + GetAndCheckSignatureToken(6, sigReader); + field.Type = this.ParseTypeSignature(sigReader); + RequiredModifier reqMod = field.Type as RequiredModifier; + if (reqMod != null && reqMod.Modifier == CoreSystemTypes.IsVolatile) + { + field.IsVolatile = true; + field.Type = reqMod.ModifiedType; + } + if ((field.Flags & FieldFlags.HasDefault) != 0) + field.DefaultValue = this.GetLiteral(i << 2, field.Type); + if ((field.Flags & FieldFlags.HasFieldMarshal) != 0) + field.MarshallingInformation = this.GetMarshallingInformation((i << 1) | 0); + if ((field.Flags & FieldFlags.HasFieldRVA) != 0) + field.InitialData = this.GetInitialData(i, field.Type, out field.section); + if (declaringType == null) + { + TypeDefRow[] typeDefs = this.tables.TypeDefTable; + int indx = i; + FieldPtrRow[] fieldPtrs = this.tables.FieldPtrTable; + int n = fieldPtrs.Length; + for (int j = 0; j < n; j++) + { + if (fieldPtrs[j].Field == i) + { + indx = j + 1; break; + } + } + n = typeDefs.Length; + for (int j = n - 1; j >= 0; j--) + { //TODO: binary search + TypeDefRow tdr = typeDefs[j]; + if (tdr.FieldList <= indx) + { + declaringType = this.GetTypeFromDef(j + 1); + break; + } + } + } + field.DeclaringType = declaringType; + if (declaringType != null && (declaringType.Flags & TypeFlags.ExplicitLayout) != 0) + { + FieldLayoutRow[] fieldLayouts = this.tables.FieldLayoutTable; + int n = fieldLayouts.Length; + for (int j = n - 1; j >= 0; j--) + { //TODO: binary search + FieldLayoutRow flr = fieldLayouts[j]; + if (flr.Field == i) + { + field.Offset = flr.Offset; + break; + } + } + } + return field; + } + private byte[] GetInitialData(int fieldIndex, TypeNode fieldType, out PESection targetSection) + { + targetSection = PESection.Text; + FieldRvaRow[] fieldRvaTable = this.tables.FieldRvaTable; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.FieldRva) % 2 == 1; + int i = 0, n = fieldRvaTable.Length, j = n - 1; + if (n == 0) return null; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (fieldRvaTable[k].Field < fieldIndex) + i = k + 1; + else + j = k; + } + } + else + for (; i < j; i++) + if (fieldRvaTable[i].Field == fieldIndex) break; + FieldRvaRow frr = fieldRvaTable[i]; + if (frr.Field != fieldIndex) return null; + Field fld = this.tables.FieldTable[fieldIndex - 1].Field; + if (fld != null) fld.Offset = frr.RVA; + fieldType = TypeNode.StripModifiers(fieldType); + EnumNode enumType = fieldType as EnumNode; + if (enumType != null) fieldType = TypeNode.StripModifiers(enumType.UnderlyingType); + if (fieldType == null) { Debug.Fail(""); return null; } + int size = fieldType.ClassSize; + if (size <= 0) + { + switch (fieldType.typeCode) + { + case ElementType.Boolean: size = 1; break; + case ElementType.Char: size = 2; break; + case ElementType.Double: size = 8; break; + case ElementType.Int16: size = 2; break; + case ElementType.Int32: size = 4; break; + case ElementType.Int64: size = 8; break; + case ElementType.Int8: size = 1; break; + case ElementType.Single: size = 4; break; + case ElementType.UInt16: size = 2; break; + case ElementType.UInt32: size = 4; break; + case ElementType.UInt64: size = 8; break; + case ElementType.UInt8: size = 1; break; + default: + if (fieldType is Pointer || fieldType is FunctionPointer) + { + size = 4; break; + } + //TODO: this seems wrong + if (i < n - 1) + size = fieldRvaTable[i + 1].RVA - frr.RVA; + else if (targetSection != PESection.Text) + size = this.tables.GetOffsetToEndOfSection(frr.RVA); + break; + } + } + if (size <= 0) return null; + if (this.tables.NoOffsetFor(frr.RVA) || this.tables.NoOffsetFor(frr.RVA + size - 1)) + return null; + MemoryCursor c = this.tables.GetNewCursor(frr.RVA, out targetSection); + byte[] result = new byte[size]; + for (i = 0; i < size; i++) + result[i] = c.ReadByte(); + return result; + } + private Literal GetLiteral(int parentCodedIndex, TypeNode/*!*/ type) + { + ConstantRow[] constants = this.tables.ConstantTable; + //TODO: do a binary search + for (int i = 0, n = constants.Length; i < n; i++) + { + if (constants[i].Parent != parentCodedIndex) continue; + object value = this.tables.GetValueFromBlob(constants[i].Type, constants[i].Value); + TypeCode valTypeCode = System.Convert.GetTypeCode(value); + TypeNode underlyingType = type; + if (type is EnumNode) underlyingType = ((EnumNode)type).UnderlyingType; + if (underlyingType.TypeCode != valTypeCode) type = CoreSystemTypes.Object; + if (type == CoreSystemTypes.Object && value != null) + { + switch (valTypeCode) + { + case TypeCode.Boolean: type = CoreSystemTypes.Boolean; break; + case TypeCode.Byte: type = CoreSystemTypes.UInt8; break; + case TypeCode.Char: type = CoreSystemTypes.Char; break; + case TypeCode.Double: type = CoreSystemTypes.Double; break; + case TypeCode.Int16: type = CoreSystemTypes.Int16; break; + case TypeCode.Int32: type = CoreSystemTypes.Int32; break; + case TypeCode.Int64: type = CoreSystemTypes.Int64; break; + case TypeCode.SByte: type = CoreSystemTypes.Int8; break; + case TypeCode.Single: type = CoreSystemTypes.Single; break; + case TypeCode.String: type = CoreSystemTypes.String; break; + case TypeCode.UInt16: type = CoreSystemTypes.UInt16; break; + case TypeCode.UInt32: type = CoreSystemTypes.UInt32; break; + case TypeCode.UInt64: type = CoreSystemTypes.UInt64; break; + case TypeCode.Empty: + case TypeCode.Object: type = CoreSystemTypes.Type; break; + } + } + return new Literal(value, type); + } + throw new InvalidMetadataException(ExceptionStrings.BadConstantParentIndex); + } + internal FunctionPointer GetCalliSignature(int ssigToken) + { +#if !FxCop + StandAloneSigRow ssr = this.tables.StandAloneSigTable[(ssigToken & 0xFFFFFF) - 1]; +#else + int index = (ssigToken & 0xFFFFFF) - 1; + if (index < 0 || index >= this.tables.StandAloneSigTable.Length) + return null; + + StandAloneSigRow ssr = this.tables.StandAloneSigTable[index]; +#endif + MemoryCursor sigReader = this.tables.GetBlobCursor(ssr.Signature); + return this.ParseFunctionPointer(sigReader); + } + internal void GetLocals(int localIndex, LocalList/*!*/ locals, Hashtable/*!*/ localSourceNames) + { + if (localIndex == 0) return; + StandAloneSigRow ssr = this.tables.StandAloneSigTable[(localIndex & 0xFFFFFF) - 1]; + this.tables.GetSignatureLength(ssr.Signature); + MemoryCursor sigReader = this.tables.GetNewCursor(); + if (sigReader.ReadByte() != 0x7) throw new InvalidMetadataException(ExceptionStrings.InvalidLocalSignature); + int count = sigReader.ReadCompressedInt(); + for (int i = 0; i < count; i++) + { + string lookupName = (string)localSourceNames[i]; +#if !FxCop + string name = lookupName == null ? "local" + i : lookupName; +#else + string name = lookupName == null ? "local$"+i : lookupName; +#endif + bool pinned = false; + TypeNode locType = this.ParseTypeSignature(sigReader, ref pinned); + Local loc = new Local(Identifier.For(name), locType); + loc.Pinned = pinned; + locals.Add(loc); + } + } +#if !ROTOR && !UseSingularityPDB + internal void GetLocalSourceNames(ISymUnmanagedScope/*!*/ scope, Hashtable/*!*/ localSourceNames) + { + uint numLocals = scope.GetLocalCount(); + IntPtr[] localPtrs = new IntPtr[numLocals]; + scope.GetLocals((uint)localPtrs.Length, out numLocals, localPtrs); + + char[] nameBuffer = new char[100]; + uint nameLen; + for (int i = 0; i < numLocals; i++) + { + ISymUnmanagedVariable local = + (ISymUnmanagedVariable)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(localPtrs[i], typeof(ISymUnmanagedVariable)); + if (local != null) + { + local.GetName((uint)nameBuffer.Length, out nameLen, nameBuffer); + int localIndex = (int)local.GetAddressField1(); + localSourceNames[localIndex] = new String(nameBuffer, 0, (int)nameLen - 1); + System.Runtime.InteropServices.Marshal.ReleaseComObject(local); + } + System.Runtime.InteropServices.Marshal.Release(localPtrs[i]); + } + + IntPtr[] subscopes = new IntPtr[100]; + uint numScopes; + scope.GetChildren((uint)subscopes.Length, out numScopes, subscopes); + for (int i = 0; i < numScopes; i++) + { + ISymUnmanagedScope subscope = + (ISymUnmanagedScope)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(subscopes[i], typeof(ISymUnmanagedScope)); + if (subscope != null) + { + this.GetLocalSourceNames(subscope, localSourceNames); + System.Runtime.InteropServices.Marshal.ReleaseComObject(subscope); + } + System.Runtime.InteropServices.Marshal.Release(subscopes[i]); + //TODO: need to figure out how map these scope to blocks and set HasLocals on those blocks + } + } +#endif + private MarshallingInformation GetMarshallingInformation(int parentCodedIndex) + { + FieldMarshalRow[] mtypes = this.tables.FieldMarshalTable; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.FieldMarshal) % 2 == 1; + int i = 0, n = mtypes.Length, j = n - 1; + if (n == 0) return null; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (mtypes[k].Parent < parentCodedIndex) + i = k + 1; + else + j = k; + } + while (i > 0 && mtypes[i - 1].Parent == parentCodedIndex) i--; + } + else + for (; i < j; i++) + if (mtypes[i].Parent == parentCodedIndex) break; + FieldMarshalRow fmr = mtypes[i]; + if (fmr.Parent != parentCodedIndex) return null; + MarshallingInformation result = new MarshallingInformation(); + int blobSize = 0; + MemoryCursor c = this.tables.GetBlobCursor(fmr.NativeType, out blobSize); + int initialPosition = c.Position; + result.NativeType = (NativeType)c.ReadByte(); + if (result.NativeType == NativeType.CustomMarshaler) + { + c.ReadUInt16(); //Skip over 0 + result.Class = ReadSerString(c); + result.Cookie = ReadSerString(c); + } + else if (blobSize > 1) + { + if (result.NativeType == NativeType.LPArray) + { + result.ElementType = (NativeType)c.ReadByte(); + result.ParamIndex = -1; + int bytesRead = 2; + if (bytesRead < blobSize) + { + int pos = c.Position; + result.ParamIndex = c.ReadCompressedInt(); + bytesRead += c.Position - pos; + if (bytesRead < blobSize) + { + pos = c.Position; + result.ElementSize = c.ReadCompressedInt(); + bytesRead += c.Position - pos; + if (bytesRead < blobSize) + result.NumberOfElements = c.ReadCompressedInt(); + } + } + } + else if (result.NativeType == NativeType.SafeArray) + { + result.ElementType = (NativeType)c.ReadByte(); //Actually a variant type. TODO: what about VT_VECTOR VT_ARRAY and VT_BYREF? + if (c.Position < initialPosition + blobSize - 1) + result.Class = ReadSerString(c); + } + else + { + result.Size = c.ReadCompressedInt(); + if (result.NativeType == NativeType.ByValArray) + { + if (blobSize > 2) + result.ElementType = (NativeType)c.ReadByte(); + else + result.ElementType = NativeType.NotSpecified; + } + } + } + return result; + } + private void GetMethodBody(Method/*!*/ method, object/*!*/ i, bool asInstructionList) + { + if (asInstructionList) { this.GetMethodInstructions(method, i); return; } + TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters; + this.currentMethodTypeParameters = method.templateParameters; + TypeNode savedCurrentType = this.currentType; + this.currentType = method.DeclaringType; + try + { + MethodRow meth = this.tables.MethodTable[((int)i) - 1]; + StatementList statements; + if (meth.RVA != 0 && (((MethodImplFlags)meth.ImplFlags) & MethodImplFlags.ManagedMask) == MethodImplFlags.Managed) + { + if (this.getDebugSymbols) this.GetMethodDebugSymbols(method, 0x6000000 | (uint)(int)i); + statements = this.ParseMethodBody(method, (int)i, meth.RVA); + } + else + statements = new StatementList(0); + method.Body = new Block(statements); +#if FxCop + if (statements.Count > 0) { + SourceContext context = statements[0].SourceContext; + method.SourceContext = context; + method.Body.SourceContext = context; + } +#endif +#if !MinimalReader + method.Body.HasLocals = true; +#endif +#if !FxCop + } + catch (Exception e) + { + if (this.module != null) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } + method.Body = new Block(new StatementList(0)); +#endif + } + finally + { + this.currentMethodTypeParameters = savedCurrentMethodTypeParameters; + this.currentType = savedCurrentType; + } + } + private void GetMethodDebugSymbols(Method/*!*/ method, uint methodToken) + //^ requires this.debugReader != null; + { +#if UseSingularityPDB + PdbFunction pdbFunc = this.GetPdbFunction(methodToken); + if (pdbFunc != null) + method.RecordSequencePoints(pdbFunc); +#elif !ROTOR + ISymUnmanagedMethod methodInfo = null; + try + { + try + { + this.debugReader.GetMethod(methodToken, ref methodInfo); + method.RecordSequencePoints(methodInfo); + } + catch (COMException) + { + } + catch (InvalidCastException) + { + } + catch (System.Runtime.InteropServices.InvalidComObjectException) { } + } + finally + { + if (methodInfo != null) + Marshal.ReleaseComObject(methodInfo); + } +#endif + } +#if UseSingularityPDB + internal PdbFunction GetPdbFunction(uint methodToken) { + PdbFunction[] pdbFunctions = this.pdbFunctions; + int i = 0, n = pdbFunctions == null ? 0 : pdbFunctions.Length, j = n-1; + while (i < j) { + int k = (i+j) / 2; + if (pdbFunctions[k].token < methodToken) + i = k+1; + else + j = k; + } + while (i > 0 && pdbFunctions[i-1].token == methodToken) i--; + if (0 <= i && i < n && pdbFunctions[i].token == methodToken) + return pdbFunctions[i]; + return null; + } +#endif + private void GetMethodInstructions(Method/*!*/ method, object/*!*/ i) + { + TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters; + this.currentMethodTypeParameters = method.templateParameters; + TypeNode savedCurrentType = this.currentType; + this.currentType = method.DeclaringType; + try + { + MethodRow meth = this.tables.MethodTable[((int)i) - 1]; + if (meth.RVA != 0 && (((MethodImplFlags)meth.ImplFlags) & MethodImplFlags.ManagedMask) == MethodImplFlags.Managed) + { + if (this.getDebugSymbols) this.GetMethodDebugSymbols(method, 0x6000000 | (uint)(int)i); + method.Instructions = this.ParseMethodInstructions(method, (int)i, meth.RVA); + } + else + method.Instructions = new InstructionList(0); +#if !FxCop + } + catch (Exception e) + { + if (this.module != null) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } + method.Instructions = new InstructionList(0); +#endif + } + finally + { + this.currentMethodTypeParameters = savedCurrentMethodTypeParameters; + this.currentType = savedCurrentType; + } + } + private Method GetMethodDefOrRef(int codedIndex) + { + switch (codedIndex & 0x1) + { + case 0x00: return this.GetMethodFromDef(codedIndex >> 1); + case 0x01: + TypeNodeList varArgTypes; + return (Method)this.GetMemberFromRef(codedIndex >> 1, out varArgTypes); + } + throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken); + } + private Method GetMethodDefOrRef(int codedIndex, int numberOfGenericArguments) + { + switch (codedIndex & 0x1) + { + case 0x00: return this.GetMethodFromDef(codedIndex >> 1); + case 0x01: + TypeNodeList varArgTypes; + return (Method)this.GetMemberFromRef(codedIndex >> 1, out varArgTypes, numberOfGenericArguments); + } + throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken); + } + internal Method/*!*/ GetMethodFromDef(int index) + { + return this.GetMethodFromDef(index, null); + } + internal Method/*!*/ GetMethodFromDef(int index, TypeNode declaringType) + { + TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters; + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + MethodRow[] methodDefs = this.tables.MethodTable; + MethodRow meth = methodDefs[index - 1]; + if (meth.Method != null) return meth.Method; + if (declaringType == null) + { + int indx = index; + MethodPtrRow[] methodPtrs = this.tables.MethodPtrTable; + int n = methodPtrs.Length, i = 0, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodPtr) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (methodPtrs[k].Method < index) + i = k + 1; + else + j = k; + } + while (i > 0 && methodPtrs[i - 1].Method == index) i--; + } + for (; i < n; i++) + { + if (methodPtrs[i].Method == index) + { + indx = i + 1; break; + } + } + TypeDefRow[] typeDefs = this.tables.TypeDefTable; + n = typeDefs.Length; i = 0; j = n - 1; + sorted = (this.sortedTablesMask >> (int)TableIndices.TypeDef) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if (typeDefs[k].MethodList < indx) + i = k + 1; + else + j = k; + } + j = i; + while (j < n - 1 && typeDefs[j + 1].MethodList == indx) j++; + } + for (; j >= 0; j--) + { + if (typeDefs[j].MethodList <= indx) + { + declaringType = this.GetTypeFromDef(j + 1); + break; + } + } + } + Method.MethodBodyProvider provider = new Method.MethodBodyProvider(this.GetMethodBody); + Identifier name = tables.GetIdentifier(meth.Name); + Method method; + if ((((MethodFlags)meth.Flags) & MethodFlags.SpecialName) != 0 && + (((MethodFlags)meth.Flags) & MethodFlags.SpecialName) != 0) + { + if (name.Name == ".ctor") + method = methodDefs[index - 1].Method = new InstanceInitializer(provider, index); + else if (name.Name == ".cctor") + method = methodDefs[index - 1].Method = new StaticInitializer(provider, index); + else + method = methodDefs[index - 1].Method = new Method(provider, index); + } + else + method = methodDefs[index - 1].Method = new Method(provider, index); + method.ProvideMethodAttributes = new Method.MethodAttributeProvider(this.GetMethodAttributes); + //method.Attributes = this.GetCustomAttributesFor((index << 5)|0); //TODO: get attributes lazily + method.Flags = (MethodFlags)meth.Flags; + method.ImplFlags = (MethodImplFlags)meth.ImplFlags; + method.Name = name; + if (declaringType != null && declaringType.IsGeneric) + { + if (declaringType.Template != null) + this.currentTypeParameters = declaringType.ConsolidatedTemplateArguments; + else + this.currentTypeParameters = declaringType.ConsolidatedTemplateParameters; + } + + tables.GetSignatureLength(meth.Signature); + MemoryCursor sigReader = this.tables.GetNewCursor(); + method.CallingConvention = (CallingConventionFlags)sigReader.ReadByte(); + if (method.IsGeneric = (method.CallingConvention & CallingConventionFlags.Generic) != 0) + { + int numTemplateParameters = sigReader.ReadCompressedInt(); + this.currentMethodTypeParameters = new TypeNodeList(numTemplateParameters); + this.currentMethodTypeParameters = method.TemplateParameters = this.GetTypeParametersFor((index << 1) | 1, method); + this.GetTypeParameterConstraints((index << 1) | 1, method.TemplateParameters); + } + int numParams = sigReader.ReadCompressedInt(); + method.ReturnType = this.ParseTypeSignature(sigReader); + if (declaringType != null && declaringType.IsValueType) + method.ThisParameter = new This(declaringType.GetReferenceType()); + else + method.ThisParameter = new This(declaringType); + ParameterList paramList = method.Parameters = new ParameterList(numParams); + if (numParams > 0) + { + int offset = method.IsStatic ? 0 : 1; + for (int i = 0; i < numParams; i++) + { + Parameter param = new Parameter(); + param.ParameterListIndex = i; + param.ArgumentListIndex = i + offset; + param.Type = this.ParseTypeSignature(sigReader); + param.DeclaringMethod = method; + paramList.Add(param); + } + int end = this.tables.ParamTable.Length + 1; + if (index < methodDefs.Length) end = methodDefs[index].ParamList; + this.AddMoreStuffToParameters(method, paramList, meth.ParamList, end); + for (int i = 0; i < numParams; i++) + { + Parameter param = paramList[i]; + if (param.Name == null) + param.Name = Identifier.For("param" + (i)); + } + } + else if (method.ReturnType != CoreSystemTypes.Void) + { + //check for custom attributes and marshalling information on return value + int i = meth.ParamList; + ParamPtrRow[] parPtrs = this.tables.ParamPtrTable; //TODO: why use ParamPtrTable in the branch and not the one above? Factor this out. + ParamRow[] pars = this.tables.ParamTable; + int n = methodDefs.Length; + int m = pars.Length; + if (index < n) m = methodDefs[index].ParamList - 1; + if (parPtrs.Length > 0) + { + if (pars != null && 0 < i && i <= m) + { + int j = parPtrs[i - 1].Param; + ParamRow pr = pars[j - 1]; + if (pr.Sequence == 0) + this.AddMoreStuffToParameters(method, null, j, j + 1); + } + } + else + { + if (pars != null && 0 < i && i <= m) + { + ParamRow pr = pars[i - 1]; + if (pr.Sequence == 0) + this.AddMoreStuffToParameters(method, null, i, i + 1); + } + } + } +#if ExtendedRuntime + for (int k = 0, al = method.ReturnAttributes == null ? 0 : method.ReturnAttributes.Count; k < al; k++) { + if (method.ReturnAttributes[k].Type == ExtendedRuntimeTypes.NotNullAttribute) { + method.ReturnType = OptionalModifier.For(ExtendedRuntimeTypes.NonNullType, method.ReturnType); + // Someone putting an attribute directly on the "real" method is still a + // kind of out-of-band contract. + // This marking is the way to signal that any override or implementing method being compiled + // should not have its non-null annotations persisted as optional modifiers. + method.HasOutOfBandContract = true; + break; + } + } +#endif + //if ((method.Flags & MethodFlags.HasSecurity) != 0) + // method.SecurityAttributes = this.GetSecurityAttributesFor((index << 2)|1); + if ((method.Flags & MethodFlags.PInvokeImpl) != 0) + { + ImplMapRow[] implMaps = this.tables.ImplMapTable; + int n = implMaps.Length, i = 0, j = n - 1; + bool sorted = (this.sortedTablesMask >> (int)TableIndices.ImplMap) % 2 == 1; + if (sorted) + { + while (i < j) + { + int k = (i + j) / 2; + if ((implMaps[k].MemberForwarded >> 1) < index) + i = k + 1; + else + j = k; + } + while (i > 0 && (implMaps[i - 1].MemberForwarded >> 1) == index) i--; + } + for (; i < n; i++) + { + ImplMapRow imr = implMaps[i]; + if (imr.MemberForwarded >> 1 == index) + { + method.PInvokeFlags = (PInvokeFlags)imr.MappingFlags; + method.PInvokeImportName = tables.GetString(imr.ImportName); + method.PInvokeModule = this.module.ModuleReferences[imr.ImportScope - 1].Module; + break; + } + } + } + method.DeclaringType = declaringType; + this.currentMethodTypeParameters = savedCurrentMethodTypeParameters; + this.currentTypeParameters = savedCurrentTypeParameters; + return method; + } + private void GetMethodAttributes(Method/*!*/ method, object/*!*/ handle) + { + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters; + try + { + MetadataReader tables = this.tables; + int index = (int)handle; + MethodRow[] methodDefs = tables.MethodTable; + int n = methodDefs.Length; + if (index < 1 || index > n) + throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + MethodRow md = methodDefs[index - 1]; + if (method != md.Method) throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + //Get custom attributes + method.Attributes = this.GetCustomAttributesFor((index << 5) | 0); + this.currentTypeParameters = savedCurrentTypeParameters; + this.currentMethodTypeParameters = savedCurrentMethodTypeParameters; + //Get security attributes + if ((method.Flags & MethodFlags.HasSecurity) != 0) + method.SecurityAttributes = this.GetSecurityAttributesFor((index << 2) | 1); +#if !FxCop + } + catch (Exception e) + { + if (this.module != null) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } + method.Attributes = new AttributeList(0); + this.currentTypeParameters = savedCurrentTypeParameters; + this.currentMethodTypeParameters = savedCurrentMethodTypeParameters; + } +#else + }finally{} +#endif + } + private Method/*!*/ GetMethodFromSpec(int i) + { + MethodSpecRow[] methodSpecs = this.tables.MethodSpecTable; + MethodSpecRow msr = methodSpecs[i - 1]; + if (msr.InstantiatedMethod != null) return msr.InstantiatedMethod; + MemoryCursor sigReader = this.tables.GetBlobCursor(msr.Instantiation); + byte header = sigReader.ReadByte(); //skip over redundant header byte + Debug.Assert(header == 0x0a); + TypeNodeList templateArguments = this.ParseTypeList(sigReader); + Method template = this.GetMethodDefOrRef(msr.Method, templateArguments.Count); + if (template == null) return new Method(); + if (template.TemplateParameters == null) return template; //Likely a dummy method + return template.GetTemplateInstance(this.currentType, templateArguments); + } + internal Member/*!*/ GetMemberFromToken(int tok) + { + TypeNodeList varArgTypes; + return this.GetMemberFromToken(tok, out varArgTypes); + } + internal Member/*!*/ GetMemberFromToken(int tok, out TypeNodeList varArgTypes) + { + varArgTypes = null; + Member member = null; + switch ((TableIndices)(tok >> 24)) + { + case TableIndices.Field: member = this.GetFieldFromDef(tok & 0xFFFFFF); break; + case TableIndices.Method: member = this.GetMethodFromDef(tok & 0xFFFFFF); break; + case TableIndices.MemberRef: member = this.GetMemberFromRef(tok & 0xFFFFFF, out varArgTypes); break; + case TableIndices.TypeDef: member = this.GetTypeFromDef(tok & 0xFFFFFF); break; + case TableIndices.TypeRef: member = this.GetTypeFromRef(tok & 0xFFFFFF); break; + case TableIndices.TypeSpec: member = this.GetTypeFromSpec(tok & 0xFFFFFF); break; + case TableIndices.MethodSpec: member = this.GetMethodFromSpec(tok & 0xFFFFFF); break; + default: throw new InvalidMetadataException(ExceptionStrings.BadMemberToken); + } + if (member == null) throw new InvalidMetadataException(ExceptionStrings.BadMemberToken); + return member; + } + internal Member GetMemberFromRef(int i, out TypeNodeList varArgTypes) + { + return this.GetMemberFromRef(i, out varArgTypes, 0); + } + internal Member GetMemberFromRef(int i, out TypeNodeList varArgTypes, int numGenericArgs) + { + MemberRefRow mref = this.tables.MemberRefTable[i - 1]; + if (mref.Member != null) + { + varArgTypes = mref.VarargTypes; + return mref.Member; + } + varArgTypes = null; + Member result = null; + int codedIndex = mref.Class; + if (codedIndex == 0) return null; + TypeNode parent = null; + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + switch (codedIndex & 0x7) + { + case 0x00: parent = this.GetTypeFromDef(codedIndex >> 3); break; + case 0x01: parent = this.GetTypeFromRef(codedIndex >> 3); break; + case 0x02: parent = this.GetTypeGlobalMemberContainerTypeFromModule(codedIndex >> 3); break; + case 0x03: result = this.GetMethodFromDef(codedIndex >> 3); + if ((((Method)result).CallingConvention & CallingConventionFlags.VarArg) != 0) + { + MemoryCursor sRdr = this.tables.GetBlobCursor(mref.Signature); + sRdr.ReadByte(); //hdr + int pCount = sRdr.ReadCompressedInt(); + this.ParseTypeSignature(sRdr); //rType + bool genParameterEncountered = false; + this.ParseParameterTypes(out varArgTypes, sRdr, pCount, ref genParameterEncountered); + } + goto done; + case 0x04: parent = this.GetTypeFromSpec(codedIndex >> 3); break; + default: throw new InvalidMetadataException(""); + } + if (parent != null && parent.IsGeneric) + { + if (parent.Template != null) + this.currentTypeParameters = parent.ConsolidatedTemplateArguments; + else + this.currentTypeParameters = parent.ConsolidatedTemplateParameters; + } + Identifier memberName = this.tables.GetIdentifier(mref.Name); + MemoryCursor sigReader = this.tables.GetBlobCursor(mref.Signature); + byte header = sigReader.ReadByte(); + if (header == 0x6) + { + TypeNode fieldType = this.ParseTypeSignature(sigReader); + TypeNode fType = TypeNode.StripModifiers(fieldType); + TypeNode parnt = parent; + while (parnt != null) + { + MemberList members = parnt.GetMembersNamed(memberName); + for (int j = 0, n = members.Count; j < n; j++) + { + Field f = members[j] as Field; + if (f == null) continue; + if (TypeNode.StripModifiers(f.Type) == fType) { result = f; goto done; } + } + Class c = parnt as Class; + if (c != null) parnt = c.BaseClass; else break; + } + if (result == null) + { + result = new Field(memberName); + result.DeclaringType = parent; + ((Field)result).Type = fieldType; + goto error; + } + goto done; + } + int typeParamCount = int.MinValue; + CallingConventionFlags callingConvention = CallingConventionFlags.Default; + if ((header & 0x20) != 0) callingConvention |= CallingConventionFlags.HasThis; + if ((header & 0x40) != 0) callingConvention |= CallingConventionFlags.ExplicitThis; + switch (header & 7) + { + case 1: callingConvention |= CallingConventionFlags.C; break; + case 2: callingConvention |= CallingConventionFlags.StandardCall; break; + case 3: callingConvention |= CallingConventionFlags.ThisCall; break; + case 4: callingConvention |= CallingConventionFlags.FastCall; break; + case 5: callingConvention |= CallingConventionFlags.VarArg; break; + } + if ((header & 0x10) != 0) + { + typeParamCount = sigReader.ReadCompressedInt(); + callingConvention |= CallingConventionFlags.Generic; + } + int paramCount = sigReader.ReadCompressedInt(); + TypeNodeList savedMethodTypeParameters = this.currentMethodTypeParameters; + this.currentTypeParameters = parent.ConsolidatedTemplateArguments; + TypeNode pnt = parent; + if (numGenericArgs > 0) + { + while (pnt != null) + { + MemberList members = pnt.GetMembersNamed(memberName); + for (int k = 0, n = members.Count; k < n; k++) + { + Method m = members[k] as Method; + if (m == null) continue; + if (m.TemplateParameters == null || m.TemplateParameters.Count != numGenericArgs) continue; + if (m.Parameters == null || m.Parameters.Count != paramCount) continue; + this.currentMethodTypeParameters = m.TemplateParameters; + this.currentTypeParameters = pnt.ConsolidatedTemplateArguments; + goto parseSignature; + } + Class c = pnt as Class; + if (c != null) pnt = c.BaseClass; else break; + } + } + parseSignature: + TypeNode returnType = this.ParseTypeSignature(sigReader); + if (returnType == null) returnType = CoreSystemTypes.Object; + bool genericParameterEncountered = returnType.IsGeneric; + TypeNodeList paramTypes = this.ParseParameterTypes(out varArgTypes, sigReader, paramCount, ref genericParameterEncountered); + this.currentMethodTypeParameters = savedMethodTypeParameters; + this.currentTypeParameters = savedCurrentTypeParameters; + pnt = parent; + while (pnt != null) + { + MemberList members = pnt.GetMembersNamed(memberName); + for (int k = 0, n = members.Count; k < n; k++) + { + Method m = members[k] as Method; + if (m == null) continue; + if (m.ReturnType == null) continue; + TypeNode mrtype = TypeNode.StripModifiers(m.ReturnType); + //^ assert mrtype != null; + if (!mrtype.IsStructurallyEquivalentTo(TypeNode.StripModifiers(returnType))) continue; + if (!m.ParameterTypesMatchStructurally(paramTypes)) continue; + if (m.CallingConvention != callingConvention) continue; + if (typeParamCount != int.MinValue && (!m.IsGeneric || m.TemplateParameters == null || m.TemplateParameters.Count != typeParamCount)) + continue; + result = m; + goto done; + } + if (memberName.UniqueIdKey == StandardIds.Ctor.UniqueIdKey) + { + //Can't run up the base class chain for constructors. + members = pnt.GetConstructors(); + if (members != null && members.Count == 1 && paramCount == 0) + { + //Only one constructor. The CLR metadata API's seem to think that this should match the empty signature + result = members[0]; + goto done; + } + break; + } + Class c = pnt as Class; + if (c != null) pnt = c.BaseClass; else break; + } + if (result == null) + { + ParameterList parameters = new ParameterList(paramCount); + for (int j = 0; j < paramCount; j++) + { + Parameter p = new Parameter(Identifier.Empty, paramTypes[j]); + parameters.Add(p); + } + //TODO: let the caller indicate if it expects a constructor + Method meth = new Method(parent, null, memberName, parameters, returnType, null); + meth.CallingConvention = callingConvention; + if ((callingConvention & CallingConventionFlags.HasThis) == 0) meth.Flags |= MethodFlags.Static; + result = meth; + } + error: + if (this.module != null) + { + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.CouldNotResolveMemberReference, parent.FullName + "::" + memberName)); + if (parent != null) parent.Members.Add(result); + } + done: + if (Reader.CanCacheMember(result)) + { + this.tables.MemberRefTable[i - 1].Member = result; + this.tables.MemberRefTable[i - 1].VarargTypes = varArgTypes; + } + this.currentTypeParameters = savedCurrentTypeParameters; + return result; + } + private static bool CanCacheMethodHelper(Method/*!*/ method) + { + if (method.IsGeneric) + { + if (method.TemplateArguments == null) + return false; + for (int i = 0; i < method.TemplateArguments.Count; i++) + if (!CanCacheTypeNode(method.TemplateArguments[i])) + return false; + } + return true; + } + private static bool CanCacheMember(Member/*!*/ member) + { + return (member.DeclaringType == null || CanCacheTypeNode(member.DeclaringType)) && + (member.NodeType != NodeType.Method || CanCacheMethodHelper((Method)member)); + } + + private TypeNodeList/*!*/ ParseParameterTypes(out TypeNodeList varArgTypes, MemoryCursor/*!*/ sigReader, int paramCount, ref bool genericParameterEncountered) + { + varArgTypes = null; + TypeNodeList paramTypes = new TypeNodeList(paramCount); + for (int j = 0; j < paramCount; j++) + { + TypeNode paramType = this.ParseTypeSignature(sigReader); + if (paramType == null) + { + //got a sentinel + varArgTypes = new TypeNodeList(paramCount - j); + j--; + continue; + } + if (varArgTypes != null) { varArgTypes.Add(paramType); continue; } + if (paramType.IsGeneric) genericParameterEncountered = true; + paramTypes.Add(paramType); + } + return paramTypes; + } + private bool TypeDefIsClass(int i) + { + if (i == 0) return false; + TypeDefRow typeDef = this.tables.TypeDefTable[i - 1]; + if (typeDef.Type != null) return typeDef.Type is Class; + if ((typeDef.Flags & (int)TypeFlags.Interface) != 0) return false; + return this.TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(typeDef.Extends); + } + private bool TypeDefIsClassButNotValueTypeBaseClass(int i) + { + if (i == 0) return false; + TypeDefRow typeDef = this.tables.TypeDefTable[i - 1]; + if (typeDef.Type != null) return typeDef.Type != CoreSystemTypes.ValueType && typeDef.Type != CoreSystemTypes.Enum && typeDef.Type is Class; + if ((typeDef.Flags & (int)TypeFlags.Interface) != 0) return false; + return this.TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(typeDef.Extends); + } + internal TypeNodeList GetInstantiatedTypes() + { + TypeNodeList result = null; + TypeDefRow[] typeDefs = this.tables.TypeDefTable; + for (int i = 0, n = typeDefs.Length; i < n; i++) + { + TypeNode t = typeDefs[i].Type; + if (t == null) continue; + if (result == null) result = new TypeNodeList(); + result.Add(t); + } + return result; + } + internal TypeNode/*!*/ GetTypeFromDef(int i) + { + TypeDefRow typeDef = this.tables.TypeDefTable[i - 1]; + if (typeDef.Type != null) return typeDef.Type; + // Save current state because the helper might change it but this method must not. + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + TypeNode savedCurrentType = this.currentType; + try + { + return this.GetTypeFromDefHelper(i); +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return new Class(); + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + return new Class(); +#endif + } + finally + { + this.currentTypeParameters = savedCurrentTypeParameters; + this.currentType = savedCurrentType; + } + } + internal TypeNode/*!*/ GetTypeFromDefHelper(int i) + { + // This is added to prevent loops. + // Check the code in GetTypeFromDef which checks != null before callig this function + this.tables.TypeDefTable[i - 1].Type = Class.Dummy; + TypeDefRow typeDef = this.tables.TypeDefTable[i - 1]; + Identifier name = this.tables.GetIdentifier(typeDef.Name); + Identifier namesp = this.tables.GetIdentifier(typeDef.Namespace); + int firstInterfaceIndex; + int lastInterfaceIndex; + this.GetInterfaceIndices(i, out firstInterfaceIndex, out lastInterfaceIndex); + InterfaceList interfaces = new InterfaceList(); + TypeNode result = this.ConstructCorrectTypeNodeSubclass(i, namesp, firstInterfaceIndex, lastInterfaceIndex, + (TypeFlags)typeDef.Flags, interfaces, typeDef.Extends, + name.UniqueIdKey == StandardIds.Enum.UniqueIdKey && namesp.UniqueIdKey == StandardIds.System.UniqueIdKey); + result.DeclaringModule = this.module; + result.Name = name; + result.Namespace = namesp; + TypeNodeList typeParameters = this.currentTypeParameters = this.GetTypeParametersFor((i << 1) | 0, result); + result.TemplateParameters = typeParameters; + result.IsGeneric = typeParameters != null; + this.tables.TypeDefTable[i - 1].Type = result; + this.currentType = result; + this.RemoveTypeParametersBelongToDeclaringType(i, ref typeParameters, result); + //Now that the type instance has been allocated, it is safe to get hold of things that could refer to this type. + if (result is Class && result.BaseType == null) + { + TypeNode baseType = this.DecodeAndGetTypeDefOrRefOrSpec(typeDef.Extends); + ((Class)result).BaseClass = baseType as Class; + if (baseType != null && !(baseType is Class) && this.module != null) + { + HandleError(this.module, ExceptionStrings.InvalidBaseClass); + } + } + if (result.IsGeneric) + this.GetTypeParameterConstraints((i << 1) | 0, typeParameters); + if (firstInterfaceIndex >= 0) + this.GetInterfaces(i, firstInterfaceIndex, interfaces); + if ((result.Flags & (TypeFlags.ExplicitLayout | TypeFlags.SequentialLayout)) != 0) + this.GetClassSizeAndPackingSize(i, result); + return result; + } + + private void GetInterfaceIndices(int i, out int firstInterfaceIndex, out int lastInterfaceIndex) + { + firstInterfaceIndex = -1; + lastInterfaceIndex = -1; + InterfaceImplRow[] intfaces = this.tables.InterfaceImplTable; + //TODO: binary search + for (int j = 0, n = intfaces.Length; j < n; j++) + { + if (intfaces[j].Class != i) continue; + if (firstInterfaceIndex == -1) + firstInterfaceIndex = j; + lastInterfaceIndex = j; + } + } + + private void GetClassSizeAndPackingSize(int i, TypeNode/*!*/ result) + { + ClassLayoutRow[] classLayouts = tables.ClassLayoutTable; + for (int j = 0, n = classLayouts.Length; j < n; j++) + { //TODO: binary search + ClassLayoutRow clr = classLayouts[j]; + if (clr.Parent == i) + { + result.ClassSize = clr.ClassSize; + result.PackingSize = clr.PackingSize; + break; + } + } + } + + private void GetInterfaces(int i, int firstInterfaceIndex, InterfaceList/*!*/ interfaces) + { + InterfaceImplRow[] intfaces = this.tables.InterfaceImplTable; + for (int j = firstInterfaceIndex, n = intfaces.Length; j < n; j++) + { + if (intfaces[j].Class != i) continue; //TODO: break if sorted + TypeNode ifaceT = this.DecodeAndGetTypeDefOrRefOrSpec(intfaces[j].Interface); + Interface iface = ifaceT as Interface; + if (iface == null) + { + iface = new Interface(); + if (ifaceT != null) + { + iface.DeclaringModule = ifaceT.DeclaringModule; + iface.Namespace = ifaceT.Namespace; + iface.Name = ifaceT.Name; + } + } + interfaces.Add(iface); + } + } + + private void RemoveTypeParametersBelongToDeclaringType(int i, ref TypeNodeList typeParameters, TypeNode/*!*/ type) + { + NestedClassRow[] nestedClasses = tables.NestedClassTable; + for (int j = 0, n = nestedClasses.Length; j < n; j++) + { //TODO: binary search + NestedClassRow ncr = nestedClasses[j]; + if (ncr.NestedClass == i) + { + type.DeclaringType = this.GetTypeFromDef(ncr.EnclosingClass); + if (type.DeclaringType != null && type.DeclaringType.IsGeneric) + { + //remove type parameters that belong to declaring type from nested type's list + if (type.templateParameters != null) + { + int icount = GetInheritedTypeParameterCount(type); + int rcount = type.templateParameters.Count; + if (icount >= rcount) + type.templateParameters = null; + else + { + TypeNodeList tpars = new TypeNodeList(rcount - icount); + for (int k = icount; k < rcount; k++) + tpars.Add(type.templateParameters[k]); + type.templateParameters = tpars; + } + this.currentTypeParameters = typeParameters = type.ConsolidatedTemplateParameters; + } + } + break; + } + } + } + + private TypeNode/*!*/ ConstructCorrectTypeNodeSubclass(int i, Identifier/*!*/ namesp, int firstInterfaceIndex, int lastInterfaceIndex, + TypeFlags flags, InterfaceList interfaces, int baseTypeCodedIndex, bool isSystemEnum) + { + TypeNode result; + TypeNode.TypeAttributeProvider attributeProvider = new TypeNode.TypeAttributeProvider(this.GetTypeAttributes); + TypeNode.NestedTypeProvider nestedTypeProvider = new TypeNode.NestedTypeProvider(this.GetNestedTypes); + TypeNode.TypeMemberProvider memberProvider = new TypeNode.TypeMemberProvider(this.GetTypeMembers); + bool isTemplateParameter = false; +#if ExtendedRuntime + InterfaceImplRow[] intfaces = this.tables.InterfaceImplTable; + Interface firstInterface = null; + Interface lastInterface = null; + if (firstInterfaceIndex >= 0){ + firstInterface = this.GetInterfaceIfNotGenericInstance(intfaces[firstInterfaceIndex].Interface); + if (firstInterface != null){ + lastInterface = this.GetInterfaceIfNotGenericInstance(intfaces[lastInterfaceIndex].Interface); + isTemplateParameter = CoreSystemTypes.IsInitialized && lastInterface != null && lastInterface == ExtendedRuntimeTypes.ITemplateParameter; + } + } +#endif + if ((flags & TypeFlags.Interface) != 0) + { + if (isTemplateParameter) + result = new TypeParameter(interfaces, nestedTypeProvider, attributeProvider, memberProvider, i); + else + result = new Interface(interfaces, nestedTypeProvider, attributeProvider, memberProvider, i); + } + else if (isTemplateParameter) + { + result = new ClassParameter(nestedTypeProvider, attributeProvider, memberProvider, i); + } + else + { + result = null; + TypeNode baseClass = this.GetTypeIfNotGenericInstance(baseTypeCodedIndex); + if (baseClass != null) + { + if (baseClass == CoreSystemTypes.MulticastDelegate) //TODO: handle single cast delegates + result = new DelegateNode(nestedTypeProvider, attributeProvider, memberProvider, i); + else if (baseClass == CoreSystemTypes.Enum) + result = new EnumNode(nestedTypeProvider, attributeProvider, memberProvider, i); + else if (baseClass == CoreSystemTypes.ValueType && + !(isSystemEnum && (flags & TypeFlags.Sealed) == 0)) + { +#if ExtendedRuntime + Struct st = null; + if (firstInterface != null){ + if (namesp.UniqueIdKey == StandardIds.StructuralTypes.UniqueIdKey){ + if (CoreSystemTypes.IsInitialized && firstInterface == ExtendedRuntimeTypes.TupleType) + st = new TupleType(nestedTypeProvider, attributeProvider, memberProvider, i); + else if (CoreSystemTypes.IsInitialized && firstInterface == ExtendedRuntimeTypes.TypeIntersection) + st = new TypeIntersection(nestedTypeProvider, attributeProvider, memberProvider, i); + else if (CoreSystemTypes.IsInitialized && firstInterface == ExtendedRuntimeTypes.TypeUnion) + st = new TypeUnion(nestedTypeProvider, attributeProvider, memberProvider, i); + else if (CoreSystemTypes.IsInitialized && firstInterface == ExtendedRuntimeTypes.ConstrainedType) + st = new ConstrainedType(nestedTypeProvider, attributeProvider, memberProvider, i); + else + st = new Struct(nestedTypeProvider, attributeProvider, memberProvider, i); + } + else if (CoreSystemTypes.IsInitialized && firstInterface == ExtendedRuntimeTypes.TypeAlias) + st = new TypeAlias(nestedTypeProvider, attributeProvider, memberProvider, i, false); + else if (CoreSystemTypes.IsInitialized && firstInterface == ExtendedRuntimeTypes.TypeDefinition) + st = new TypeAlias(nestedTypeProvider, attributeProvider, memberProvider, i, true); + } + if (st == null && lastInterface != null) { + result = this.GetTypeExtensionFromDef(nestedTypeProvider, attributeProvider, memberProvider, i, baseClass, lastInterface); + } + else { + result = st; + } + if (result == null) +#endif + result = new Struct(nestedTypeProvider, attributeProvider, memberProvider, i); + } + } + if (result == null) + { +#if ExtendedRuntime + if (lastInterface != null) + result = this.GetTypeExtensionFromDef(nestedTypeProvider, attributeProvider, memberProvider, i, baseClass, lastInterface); + if (result == null) +#endif + result = new Class(nestedTypeProvider, attributeProvider, memberProvider, i); + } + } + result.Flags = flags; + result.Interfaces = interfaces; + return result; + } +#if !MinimalReader + private TrivialHashtable/*<Ident,TypeExtensionProvider>*//*!*/ TypeExtensionTable = new TrivialHashtable(); + delegate TypeNode TypeExtensionProvider(TypeNode.NestedTypeProvider nprovider, TypeNode.TypeAttributeProvider aprovider, TypeNode.TypeMemberProvider mprovider, TypeNode baseType, object handle); + + private static TypeNode DummyTypeExtensionProvider(TypeNode.NestedTypeProvider nprovider, TypeNode.TypeAttributeProvider aprovider, TypeNode.TypeMemberProvider mprovider, TypeNode baseType, object handle) + { + return null; + } + private TypeExtensionProvider/*!*/ dummyTEProvider = new TypeExtensionProvider(DummyTypeExtensionProvider); + + private TypeNode GetTypeExtensionFromDef(TypeNode.NestedTypeProvider nestedTypeProvider, TypeNode.TypeAttributeProvider attributeProvider, TypeNode.TypeMemberProvider memberProvider, object handle, TypeNode baseType, Interface/*!*/ lastInterface) + { + if (lastInterface.Namespace.UniqueIdKey == StandardIds.CciTypeExtensions.UniqueIdKey) + { + TypeExtensionProvider teprovider = (TypeExtensionProvider)TypeExtensionTable[lastInterface.Name.UniqueIdKey]; + if (teprovider == null) + { + string loc = lastInterface.DeclaringModule.Location.ToLower(CultureInfo.InvariantCulture); + if (loc.EndsWith(".runtime.dll")) + { + loc = System.IO.Path.GetFileName(loc); + string compilerDllName = loc.Replace(".runtime.dll", ""); + System.Reflection.Assembly rassem; + try + { + rassem = System.Reflection.Assembly.Load(compilerDllName); + } + catch + { + HandleError(this.module, string.Format(CultureInfo.CurrentCulture, ExceptionStrings.CannotLoadTypeExtension, lastInterface.FullName, compilerDllName)); + goto ExtensionNotFound; + } + if (rassem == null) goto ExtensionNotFound; + System.Type tprov = rassem.GetType(StandardIds.CciTypeExtensions.Name + "." + lastInterface.Name.Name + "Provider"); + if (tprov == null) goto ExtensionNotFound; + System.Reflection.MethodInfo providerMethod = tprov.GetMethod("For"); + if (providerMethod == null) goto ExtensionNotFound; + teprovider = (TypeExtensionProvider)Delegate.CreateDelegate(typeof(TypeExtensionProvider), providerMethod); + ExtensionNotFound: ; + if (teprovider == null) + { + // install a not-found dummy provider + teprovider = this.dummyTEProvider; + } + TypeExtensionTable[lastInterface.Name.UniqueIdKey] = teprovider; + } + } + if (teprovider == null) return null; + return teprovider(nestedTypeProvider, attributeProvider, memberProvider, baseType, handle); + } + return null; + } +#endif + private static int GetInheritedTypeParameterCount(TypeNode type) + { + if (type == null) return 0; + int n = 0; + type = type.DeclaringType; + while (type != null) + { + n += type.templateParameters == null ? 0 : type.templateParameters.Count; + type = type.DeclaringType; + } + return n; + } + private TypeNode/*!*/ GetTypeGlobalMemberContainerTypeFromModule(int i) + { + ModuleRefRow mr = this.tables.ModuleRefTable[i - 1]; + Module mod = mr.Module; + TypeNode result = null; + if (mod != null && mod.Types != null && mod.Types.Count > 0) + result = mod.Types[0]; + if (result != null) return result; + result = this.GetDummyTypeNode(Identifier.Empty, Identifier.For("<Module>"), mod, null, false); + if (mod != null) mod.Types = new TypeNodeList(result); + return result; + } + internal void GetNamespaces() + //^ ensures this.namespaceTable != null; + { + TypeDefRow[] typeDefs = this.tables.TypeDefTable; + int n = typeDefs.Length; + TrivialHashtable nsT = this.namespaceTable = new TrivialHashtable(n * 2); + TrivialHashtable nsFor = new TrivialHashtable(); + NamespaceList nsL = this.namespaceList = new NamespaceList(n); + for (int i = 0; i < n; i++) + { + TypeDefRow typeDef = typeDefs[i]; + TrivialHashtable ns = (TrivialHashtable)nsT[typeDef.NamespaceKey]; + Namespace nSpace = (Namespace)nsFor[typeDef.NamespaceKey]; + if (ns == null) + { + nsT[typeDef.NamespaceKey] = ns = new TrivialHashtable(); + nsFor[typeDef.NamespaceKey] = nSpace = new Namespace(typeDef.NamespaceId); + nsL.Add(nSpace); + } + Debug.Assert(nSpace != null); + if ((typeDef.Flags & (int)TypeFlags.VisibilityMask) == 0) + ns[typeDef.NameKey] = i + 1; + else if ((typeDef.Flags & (int)TypeFlags.VisibilityMask) == 1) + { + nSpace.isPublic = true; + ns[typeDef.NameKey] = i + 1; + } + } + } + private TypeNode GetTypeFromName(Identifier/*!*/ Namespace, Identifier/*!*/ name) + { + try + { + if (this.namespaceTable == null) this.GetNamespaces(); + //^ assert this.namespaceTable != null; + TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[Namespace.UniqueIdKey]; + if (nsTable == null) return this.GetForwardedTypeFromName(Namespace, name); + object ti = nsTable[name.UniqueIdKey]; + if (ti == null) return this.GetForwardedTypeFromName(Namespace, name); + TypeNode t = this.GetTypeFromDef((int)ti); + return t; +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return null; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + return null; + } +#else + }finally{} +#endif + } + private TypeNode GetForwardedTypeFromName(Identifier/*!*/ Namespace, Identifier/*!*/ name) + { + ExportedTypeRow[] exportedTypes = this.tables.ExportedTypeTable; + for (int i = 0, n = exportedTypes == null ? 0 : exportedTypes.Length; i < n; i++) + { + ExportedTypeRow etr = exportedTypes[i]; + if ((etr.Flags & (int)TypeFlags.Forwarder) == 0) continue; + if (this.tables.GetString(etr.TypeNamespace) != Namespace.Name || + this.tables.GetString(etr.TypeName) != name.Name) continue; + int index = etr.Implementation >> 2; + AssemblyRefRow arr = this.tables.AssemblyRefTable[index - 1]; + return arr.AssemblyReference.Assembly.GetType(Namespace, name); + } + return null; + } + internal bool IsValidTypeName(Identifier/*!*/ Namespace, Identifier/*!*/ name) + { + try + { + if (this.namespaceTable == null) this.GetNamespaces(); + //^ assert this.namespaceTable != null; + TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[Namespace.UniqueIdKey]; + if (nsTable == null) return false; + return nsTable[name.UniqueIdKey] != null; +#if !FxCop + } + catch (Exception e) + { + if (this.module == null) return false; + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + return false; + } +#else + }finally{} +#endif + } + internal TypeNode/*!*/ GetTypeFromRef(int i) + { + return this.GetTypeFromRef(i, false); + } + internal TypeNode/*!*/ GetTypeFromRef(int i, bool expectStruct) + { + TypeRefRow[] trtable = this.tables.TypeRefTable; + TypeRefRow trr = trtable[i - 1]; + TypeNode result = trr.Type; + if (result != null) return result; + Identifier name = tables.GetIdentifier(trr.Name); + Identifier namesp = tables.GetIdentifier(trr.Namespace); + int resolutionScope = trr.ResolutionScope; + Module declaringModule = null; + TypeNode declaringType = null; + int index = resolutionScope >> 2; + switch (resolutionScope & 0x3) + { + case 0: + declaringModule = this.module; + //^ assume declaringModule != null; + result = declaringModule.GetType(namesp, name); + //REVIEW: deal with case where ref is in same (multi-module) assembly, but not the current module? index == 0 + break; + case 1: + declaringModule = this.tables.ModuleRefTable[index - 1].Module; + if (declaringModule != null) + result = declaringModule.GetType(namesp, name); + break; + case 2: + declaringModule = this.tables.AssemblyRefTable[index - 1].AssemblyReference.Assembly; + if (declaringModule != null) + result = declaringModule.GetType(namesp, name); + break; + case 3: + declaringType = this.GetTypeFromRef(index); + declaringModule = declaringType.DeclaringModule; + if (namesp == null || namesp.length == 0) + result = (TypeNode)declaringType.GetMembersNamed(name)[0]; + else + result = (TypeNode)declaringType.GetMembersNamed(Identifier.For(namesp.Name + "." + name.Name))[0]; + break; + default: + declaringModule = this.module; + break; + } + if (result == null) + result = this.GetDummyTypeNode(namesp, name, declaringModule, declaringType, expectStruct); + trtable[i - 1].Type = result; + if (!Reader.CanCacheTypeNode(result)) + trtable[i - 1].Type = null; + return result; + } + private TypeNode/*!*/ GetDummyTypeNode(Identifier namesp, Identifier name, Module declaringModule, TypeNode declaringType, bool expectStruct) + { + TypeNode result = null; + if (this.module != null) + { + string modName = declaringModule == null ? "" : declaringModule.Name == null ? "" : declaringModule.Name.ToString(); + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.CouldNotResolveTypeReference, + "[" + modName + "]" + namesp + "." + name)); + } + result = expectStruct ? (TypeNode)new Struct() : (TypeNode)new Class(); + if (name != null && name.ToString().StartsWith("I") && name.ToString().Length > 1 && char.IsUpper(name.ToString()[1])) + result = new Interface(); + result.Flags |= TypeFlags.Public; + result.Name = name; + result.Namespace = namesp; + if (declaringType != null) + { + result.DeclaringType = declaringType; + result.DeclaringType.DeclaringModule = declaringType.DeclaringModule; + declaringType.Members.Add(result); + } + else + { + if (declaringModule == null) declaringModule = this.module; + //^ assume declaringModule != null; + result.DeclaringModule = declaringModule; + if (declaringModule.types != null) + declaringModule.types.Add(result); + } + return result; + } + private bool TypeSpecIsClass(int i) + { + TypeSpecRow tsr = this.tables.TypeSpecTable[i - 1]; + if (tsr.Type != null) return tsr.Type is Class; + this.tables.GetSignatureLength(tsr.Signature); + return this.TypeSignatureIsClass(this.tables.GetNewCursor()); + } + internal TypeNode/*!*/ GetTypeFromSpec(int i) + { + TypeSpecRow tsr = this.tables.TypeSpecTable[i - 1]; + if (tsr.Type != null) return tsr.Type; + this.tables.GetSignatureLength(tsr.Signature); + bool pinned = false; + bool isTypeArgument = false; + TypeNode result = this.ParseTypeSignature(this.tables.GetNewCursor(), ref pinned, ref isTypeArgument); + if (result == null) result = new Class(); + //Get custom attributes + AttributeList attributes = this.GetCustomAttributesFor((i << 5) | 13); + if (attributes.Count > 0) + { + //Append attributes "inherited" from template to metadata attributes + AttributeList templAttributes = result.Attributes; + for (int j = 0, n = templAttributes == null ? 0 : templAttributes.Count; j < n; j++) + { + AttributeNode attr = result.Attributes[j]; + if (attr == null) continue; + attributes.Add(attr); + } + result.Attributes = attributes; + } +#if ExtendedRuntime + for (int j = 0, n = attributes.Count; j < n; j++) { + if (attributes[j].Type == SystemTypes.NotNullGenericArgumentsAttribute) { + Literal l = (Literal)attributes[j].Expressions[0]; + string s = (string)l.Value; + TypeNodeList ts = new TypeNodeList(s.Length); + for (int k = 0, m = s.Length; k < m; k++) { + if (s[k] == '!') + ts.Add(OptionalModifier.For(ExtendedRuntimeTypes.NonNullType, result.ConsolidatedTemplateArguments[k])); + else + ts.Add(result.ConsolidatedTemplateArguments[k]); + } + result = result.Template.GetGenericTemplateInstance(this.module, ts); + //^ assume result != null; + } + } +#endif + if (!isTypeArgument && Reader.CanCacheTypeNode(result)) + this.tables.TypeSpecTable[i - 1].Type = result; + return result; + } + private static bool CanCacheTypeNode(TypeNode/*!*/ type) + { +#if WHIDBEY + return !type.IsGeneric && (type.Template == null || !type.IsNotFullySpecialized) && + type.NodeType != NodeType.TypeParameter && type.NodeType != NodeType.ClassParameter && + type.NodeType != NodeType.InterfaceExpression; +#else + return true; +#endif + } + private static Module GetNestedModule(Module module, string modName, ref string modLocation) + { + if (module == null || modName == null) { Debug.Assert(false); return null; } + Module mod = module.GetNestedModule(modName); + if (mod == null) + { + if (module.Location != null) + modLocation = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(module.Location), modName); + if (modLocation != null && System.IO.File.Exists(modLocation)) + { + mod = Module.GetModule(modLocation); + if (mod != null) + { + mod.ContainingAssembly = module.ContainingAssembly; + module.ModuleReferences.Add(new ModuleReference(modName, mod)); + } + } + } + if (mod == null) + { + HandleError(module, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.CouldNotFindReferencedModule, modLocation)); + mod = new Module(); + mod.Name = modName; + mod.ContainingAssembly = module.ContainingAssembly; + mod.Kind = ModuleKindFlags.DynamicallyLinkedLibrary; + } + return mod; + } + private void GetTypeList(Module/*!*/ module) + { + TypeNodeList types = new TypeNodeList(); + TypeDefRow[] typeDefs = this.tables.TypeDefTable; + for (int i = 0, n = typeDefs.Length; i < n; i++) + { + TypeNode t = this.GetTypeFromDef(i + 1); + if (t != null && t.DeclaringType == null) types.Add(t); + } + module.Types = types; + AssemblyNode assem = module as AssemblyNode; + if (assem == null) return; + types = new TypeNodeList(); + ExportedTypeRow[] exportedTypes = this.tables.ExportedTypeTable; + for (int i = 0, n = exportedTypes.Length; i < n; i++) + { + ExportedTypeRow etr = exportedTypes[i]; + Identifier nameSpace = Identifier.For(this.tables.GetString(etr.TypeNamespace)); + Identifier typeName = Identifier.For(this.tables.GetString(etr.TypeName)); + TypeNode exportedType = null; + switch (etr.Implementation & 0x3) + { + case 0: + string modName = this.tables.GetString(this.tables.FileTable[(etr.Implementation >> 2) - 1].Name); + string modLocation = modName; + Module mod = GetNestedModule(assem, modName, ref modLocation); + if (mod == null) { Debug.Assert(false); break; } + exportedType = mod.GetType(nameSpace, typeName); + if (exportedType == null) + { + HandleError(assem, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.CouldNotFindExportedTypeInModule, nameSpace + "." + typeName, modLocation)); + exportedType = new Class(); + exportedType.Name = typeName; + exportedType.Namespace = nameSpace; + exportedType.Flags = TypeFlags.Class | TypeFlags.Public; + exportedType.DeclaringModule = mod; + } + break; + case 1: + AssemblyReference aref = this.tables.AssemblyRefTable[(etr.Implementation >> 2) - 1].AssemblyReference; + if (aref == null) + { + HandleError(assem, ExceptionStrings.BadMetadataInExportTypeTableNoSuchAssemblyReference); + aref = new AssemblyReference("dummy assembly for bad reference"); + } + AssemblyNode a = aref.Assembly; + if (a == null) { Debug.Assert(false); continue; } + exportedType = a.GetType(nameSpace, typeName); + if (exportedType == null) + { + HandleError(assem, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.CouldNotFindExportedTypeInAssembly, nameSpace + "." + typeName, a.StrongName)); + exportedType = new Class(); + exportedType.Name = typeName; + exportedType.Namespace = nameSpace; + exportedType.Flags = TypeFlags.Class | TypeFlags.Public; + exportedType.DeclaringModule = a; + } + break; + case 2: + TypeNode parentType = types[(etr.Implementation >> 2) - 1]; + if (parentType == null) + { + HandleError(assem, ExceptionStrings.BadMetadataInExportTypeTableNoSuchParentType); + parentType = new Class(); + parentType.DeclaringModule = this.module; + parentType.Name = Identifier.For("Missing parent type"); + } + exportedType = parentType.GetNestedType(typeName); + if (exportedType == null) + { + HandleError(assem, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.CouldNotFindExportedNestedTypeInType, typeName, parentType.FullName)); + exportedType = new Class(); + exportedType.Name = typeName; + exportedType.Flags = TypeFlags.Class | TypeFlags.NestedPublic; + exportedType.DeclaringType = parentType; + exportedType.DeclaringModule = parentType.DeclaringModule; + } + break; + } + types.Add(exportedType); + } + assem.ExportedTypes = types; + } + private void GetNestedTypes(TypeNode/*!*/ type, object/*!*/ handle) + { + type.nestedTypes = null; + TypeNodeList result = new TypeNodeList(); +#if !FxCop + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; +#endif + try + { + if (type.IsGeneric) + { + if (type.templateParameters == null) type.templateParameters = new TypeNodeList(0); + this.currentTypeParameters = type.ConsolidatedTemplateParameters; + } + this.currentType = type; + TypeNode declaringType = type.DeclaringType; + while (this.currentTypeParameters == null && declaringType != null) + { + if (declaringType.IsGeneric) + { + if (declaringType.templateParameters == null) declaringType.templateParameters = new TypeNodeList(0); + this.currentTypeParameters = declaringType.ConsolidatedTemplateParameters; + } + declaringType = declaringType.DeclaringType; + } + MetadataReader tables = this.tables; + int typeTableIndex = (int)handle; + TypeDefRow[] typeDefs = tables.TypeDefTable; + int n = typeDefs.Length; + if (typeTableIndex < 1 || typeTableIndex > n) + throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + NestedClassRow[] nestedClasses = tables.NestedClassTable; + n = nestedClasses.Length; + for (int i = 0; i < n; i++) + { //TODO: binary lookup + NestedClassRow ncr = nestedClasses[i]; + if (ncr.EnclosingClass != typeTableIndex) continue; + TypeNode t = this.GetTypeFromDef(ncr.NestedClass); + if (t != null) + { + if (type.nestedTypes != null) return; //A recursive call to GetNestedTypes has already done the deed + t.DeclaringType = type; + if ((t.Flags & TypeFlags.RTSpecialName) == 0 || t.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey) + result.Add(t); + } + else + { + throw new InvalidMetadataException("Invalid nested class row"); + } + } + type.nestedTypes = result; +#if !FxCop + } + catch (Exception e) + { + if (this.module != null) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } + this.currentTypeParameters = savedCurrentTypeParameters; + } +#else + }finally{} +#endif + } + private void GetTypeMembers(TypeNode/*!*/ type, object/*!*/ handle) + { + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + try + { + MetadataReader tables = this.tables; + int typeTableIndex = (int)handle; + TypeDefRow[] typeDefs = tables.TypeDefTable; + FieldRow[] fieldDefs = tables.FieldTable; + FieldPtrRow[] fieldPtrs = tables.FieldPtrTable; + MethodRow[] methodDefs = tables.MethodTable; + MethodPtrRow[] methodPtrs = tables.MethodPtrTable; + EventMapRow[] eventMaps = tables.EventMapTable; + EventRow[] eventDefs = tables.EventTable; + EventPtrRow[] eventPtrs = tables.EventPtrTable; + MethodImplRow[] methodImpls = tables.MethodImplTable; + PropertyMapRow[] propertyMaps = tables.PropertyMapTable; + PropertyPtrRow[] propertyPtrs = tables.PropertyPtrTable; + PropertyRow[] propertyDefs = this.tables.PropertyTable; + NestedClassRow[] nestedClasses = tables.NestedClassTable; + int n = typeDefs.Length; + if (typeTableIndex < 1 || typeTableIndex > n) + throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + TypeDefRow td = typeDefs[typeTableIndex - 1]; + if (type != td.Type) throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + //Get type members + if (type.IsGeneric) + { + if (type.templateParameters == null) type.templateParameters = new TypeNodeList(0); + this.currentTypeParameters = type.ConsolidatedTemplateParameters; + } + this.currentType = type; + TypeNode declaringType = type.DeclaringType; + while (this.currentTypeParameters == null && declaringType != null) + { + if (declaringType.IsGeneric) + { + if (declaringType.templateParameters == null) declaringType.templateParameters = new TypeNodeList(0); + this.currentTypeParameters = declaringType.ConsolidatedTemplateParameters; + } + declaringType = declaringType.DeclaringType; + } + type.members = new MemberList(); + n = nestedClasses.Length; + for (int i = 0; i < n; i++) + { + NestedClassRow ncr = nestedClasses[i]; + if (ncr.EnclosingClass != typeTableIndex) continue; + TypeNode t = this.GetTypeFromDef(ncr.NestedClass); + if (t != null) + { + t.DeclaringType = type; + if ((t.Flags & TypeFlags.RTSpecialName) == 0 || t.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey) + type.Members.Add(t); + } + } + n = typeDefs.Length; + int m = fieldDefs.Length; + int start = td.FieldList; + int end = m + 1; if (typeTableIndex < n) end = typeDefs[typeTableIndex].FieldList; + if (type is EnumNode) this.GetUnderlyingTypeOfEnumNode((EnumNode)type, fieldDefs, fieldPtrs, start, end); + this.AddFieldsToType(type, fieldDefs, fieldPtrs, start, end); + m = methodDefs.Length; + start = td.MethodList; + end = m + 1; if (typeTableIndex < n) end = typeDefs[typeTableIndex].MethodList; + this.AddMethodsToType(type, methodPtrs, start, end); + n = propertyMaps.Length; + m = propertyDefs.Length; + for (int i = 0; i < n; i++) + { //TODO: binary search + PropertyMapRow pm = propertyMaps[i]; + if (pm.Parent != typeTableIndex) continue; + start = pm.PropertyList; + end = m + 1; if (i < n - 1) end = propertyMaps[i + 1].PropertyList; + this.AddPropertiesToType(type, propertyDefs, propertyPtrs, start, end); + } + n = eventMaps.Length; + m = eventDefs.Length; + for (int i = 0; i < n; i++) + { //TODO: binary search + EventMapRow em = eventMaps[i]; + if (em.Parent != typeTableIndex) continue; + start = em.EventList; + end = m + 1; if (i < n - 1) end = eventMaps[i + 1].EventList; + this.AddEventsToType(type, eventDefs, eventPtrs, start, end); + } + n = methodImpls.Length; + for (int i = 0; i < n; i++) + { //TODO: binary search + MethodImplRow mir = methodImpls[i]; + if (mir.Class != typeTableIndex) continue; + Method implementer = this.GetMethodDefOrRef(mir.MethodBody); + if (implementer == null) continue; + MethodList implementedInterfaceMethods = implementer.ImplementedInterfaceMethods; + if (implementedInterfaceMethods == null) + implementedInterfaceMethods = implementer.ImplementedInterfaceMethods = new MethodList(); + TypeNodeList savedMethodTypeParameters = this.currentMethodTypeParameters; + this.currentMethodTypeParameters = implementer.TemplateParameters; + implementedInterfaceMethods.Add(this.GetMethodDefOrRef(mir.MethodDeclaration)); + this.currentMethodTypeParameters = savedMethodTypeParameters; + } + this.currentTypeParameters = savedCurrentTypeParameters; +#if !FxCop + } + catch (Exception e) + { + if (this.module != null) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } + type.Members = new MemberList(0); + this.currentTypeParameters = savedCurrentTypeParameters; + } +#else + }finally{} +#endif + } + private void GetTypeAttributes(TypeNode/*!*/ type, object/*!*/ handle) + { + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + try + { + MetadataReader tables = this.tables; + int typeTableIndex = (int)handle; + TypeDefRow[] typeDefs = tables.TypeDefTable; + int n = typeDefs.Length; + if (typeTableIndex < 1 || typeTableIndex > n) + throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + TypeDefRow td = typeDefs[typeTableIndex - 1]; + if (type != td.Type) throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex); + //Get custom attributes + type.Attributes = this.GetCustomAttributesFor((typeTableIndex << 5) | 3); + this.currentTypeParameters = savedCurrentTypeParameters; + //Get security attributes + if ((type.Flags & TypeFlags.HasSecurity) != 0) + type.SecurityAttributes = this.GetSecurityAttributesFor((typeTableIndex << 2) | 0); +#if !FxCop + } + catch (Exception e) + { + if (this.module != null) + { + if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList(); + this.module.MetadataImportErrors.Add(e); + } + type.Attributes = new AttributeList(0); + this.currentTypeParameters = savedCurrentTypeParameters; + } +#else + }finally{} +#endif + } + private TypeNodeList/*!*/ ParseTypeList(MemoryCursor/*!*/ sigReader) + { + int n = sigReader.ReadCompressedInt(); + TypeNodeList result = new TypeNodeList(n); + for (int i = 0; i < n; i++) + { + TypeNode t = this.ParseTypeSignature(sigReader); + if (t == null || t == Struct.Dummy) + { + //Can happen when dealing with a primitive type that implements an interface that references the primitive type. + //For example, System.String implements IComparable<System.String>. + if (this.currentType != null && !CoreSystemTypes.Initialized) + t = this.currentType; + else + { + Debug.Assert(false); + t = new TypeParameter(); + t.Name = Identifier.For("Bad type parameter in position " + i); + t.DeclaringModule = this.module; + } + } + result.Add(t); + } + return result; + } + private bool TypeSignatureIsClass(MemoryCursor/*!*/ sigReader) + { + ElementType tok = (ElementType)sigReader.ReadCompressedInt(); + switch (tok) + { + case ElementType.Pinned: + case ElementType.Pointer: + case ElementType.Reference: + return this.TypeSignatureIsClass(sigReader); + case ElementType.OptionalModifier: + case ElementType.RequiredModifier: + sigReader.ReadCompressedInt(); + return this.TypeSignatureIsClass(sigReader); + case ElementType.Class: + return true; + case ElementType.GenericTypeInstance: + return this.TypeSignatureIsClass(sigReader); + case ElementType.TypeParameter: + { + int pnum = sigReader.ReadCompressedInt(); + if (this.currentTypeParameters != null && this.currentTypeParameters.Count > pnum) + { + TypeNode tPar = this.currentTypeParameters[pnum]; + return tPar != null && tPar is Class; + } + return false; + } + case ElementType.MethodParameter: + { + int pnum = sigReader.ReadCompressedInt(); + if (this.currentMethodTypeParameters != null && this.currentMethodTypeParameters.Count > pnum) + { + TypeNode tPar = this.currentMethodTypeParameters[pnum]; + return tPar != null && tPar is Class; + } + return false; + } + default: + return false; + } + } + private TypeNode ParseTypeSignature(MemoryCursor/*!*/ sigReader) + { + bool junk = false; + return this.ParseTypeSignature(sigReader, ref junk, ref junk); + } + private TypeNode ParseTypeSignature(MemoryCursor/*!*/ sigReader, ref bool pinned) + { + bool junk = false; + return this.ParseTypeSignature(sigReader, ref pinned, ref junk); + } + private TypeNode ParseTypeSignature(MemoryCursor/*!*/ sigReader, ref bool pinned, ref bool isTypeArgument) + { + TypeNode elementType; + ElementType tok = (ElementType)sigReader.ReadCompressedInt(); + if (tok == ElementType.Pinned) + { + pinned = true; + tok = (ElementType)sigReader.ReadCompressedInt(); + } + switch (tok) + { + case ElementType.Boolean: return CoreSystemTypes.Boolean; + case ElementType.Char: return CoreSystemTypes.Char; + case ElementType.Double: return CoreSystemTypes.Double; + case ElementType.Int16: return CoreSystemTypes.Int16; + case ElementType.Int32: return CoreSystemTypes.Int32; + case ElementType.Int64: return CoreSystemTypes.Int64; + case ElementType.Int8: return CoreSystemTypes.Int8; + case ElementType.IntPtr: return CoreSystemTypes.IntPtr; + case ElementType.BoxedEnum: + case ElementType.Object: return CoreSystemTypes.Object; + case ElementType.Single: return CoreSystemTypes.Single; + case ElementType.String: return CoreSystemTypes.String; + case ElementType.DynamicallyTypedReference: return CoreSystemTypes.DynamicallyTypedReference; + case ElementType.UInt16: return CoreSystemTypes.UInt16; + case ElementType.UInt32: return CoreSystemTypes.UInt32; + case ElementType.UInt64: return CoreSystemTypes.UInt64; + case ElementType.UInt8: return CoreSystemTypes.UInt8; + case ElementType.UIntPtr: return CoreSystemTypes.UIntPtr; + case ElementType.Void: return CoreSystemTypes.Void; + case ElementType.Pointer: + elementType = this.ParseTypeSignature(sigReader, ref pinned); + if (elementType == null) elementType = CoreSystemTypes.Object; + if (elementType == null) return null; + return elementType.GetPointerType(); + case ElementType.Reference: + elementType = this.ParseTypeSignature(sigReader, ref pinned); + if (elementType == null) elementType = CoreSystemTypes.Object; + return elementType.GetReferenceType(); + case ElementType.FunctionPointer: + return this.ParseFunctionPointer(sigReader); + case ElementType.OptionalModifier: + case ElementType.RequiredModifier: + TypeNode modifier = this.DecodeAndGetTypeDefOrRefOrSpec(sigReader.ReadCompressedInt()); + if (modifier == null) modifier = CoreSystemTypes.Object; + TypeNode modified = this.ParseTypeSignature(sigReader, ref pinned); + if (modified == null) modified = CoreSystemTypes.Object; + if (modified == null || modified == null) return null; + if (tok == ElementType.RequiredModifier) + return RequiredModifier.For(modifier, modified); + else + return OptionalModifier.For(modifier, modified); + case ElementType.Class: + return this.DecodeAndGetTypeDefOrRefOrSpec(sigReader.ReadCompressedInt()); + case ElementType.ValueType: + return this.DecodeAndGetTypeDefOrRefOrSpec(sigReader.ReadCompressedInt(), true); + case ElementType.TypeParameter: + TypeNode tPar = null; + int pnum = sigReader.ReadCompressedInt(); + if (this.currentTypeParameters != null && this.currentTypeParameters.Count > pnum) + tPar = this.currentTypeParameters[pnum]; + if (tPar == null) + { + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.BadTypeParameterInPositionForType, pnum, this.currentType == null ? "" : this.currentType.FullName)); + tPar = new TypeParameter(); + tPar.Name = Identifier.For("Bad type parameter in position " + pnum); + tPar.DeclaringModule = this.module; + } + isTypeArgument = true; + return tPar; + case ElementType.MethodParameter: + TypeNode mTPar = null; + pnum = sigReader.ReadCompressedInt(); + if (this.currentMethodTypeParameters != null && this.currentMethodTypeParameters.Count > pnum) + mTPar = this.currentMethodTypeParameters[pnum]; + if (mTPar == null) + { + HandleError(this.module, String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.BadMethodTypeParameterInPosition, pnum)); + mTPar = new MethodTypeParameter(); + mTPar.Name = Identifier.For("Bad method type parameter in position " + pnum); + } + isTypeArgument = true; + return mTPar; + case ElementType.GenericTypeInstance: + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + TypeNode template = this.ParseTypeSignature(sigReader, ref pinned); + this.currentTypeParameters = savedCurrentTypeParameters; + if (template == null || template.ConsolidatedTemplateParameters == null) return template; //Likely a dummy type + if (CoreSystemTypes.Initialized) + { + if (this.currentTypeParameters == null || this.currentTypeParameters.Count == 0) + this.currentTypeParameters = template.ConsolidatedTemplateParameters; + TypeNodeList genArgs = this.ParseTypeList(sigReader); + if (this.module == null) return null; + TypeNode genInst = template.GetGenericTemplateInstance(this.module, genArgs); + this.currentTypeParameters = savedCurrentTypeParameters; + return genInst; + } + InterfaceExpression ifaceExpr = new InterfaceExpression(null); + ifaceExpr.Template = template; + ifaceExpr.Namespace = template.Namespace; + ifaceExpr.Name = template.Name; + ifaceExpr.TemplateArguments = this.ParseTypeList(sigReader); + this.currentTypeParameters = savedCurrentTypeParameters; + return ifaceExpr; + case ElementType.SzArray: + elementType = this.ParseTypeSignature(sigReader, ref pinned); + if (elementType == null) elementType = CoreSystemTypes.Object; + if (elementType == null) return null; + return elementType.GetArrayType(1); + case ElementType.Array: + elementType = this.ParseTypeSignature(sigReader, ref pinned); + if (elementType == null) elementType = CoreSystemTypes.Object; + if (elementType == null) return null; + int rank = sigReader.ReadCompressedInt(); + int numSizes = sigReader.ReadCompressedInt(); + int[] sizes = new int[numSizes]; + for (int i = 0; i < numSizes; i++) sizes[i] = sigReader.ReadCompressedInt(); + int numLoBounds = sigReader.ReadCompressedInt(); + int[] loBounds = new int[numLoBounds]; + for (int i = 0; i < numLoBounds; i++) loBounds[i] = sigReader.ReadCompressedInt(); + return elementType.GetArrayType(rank, numSizes, numLoBounds, sizes, loBounds); + case ElementType.Sentinel: return null; + case ElementType.Type: return CoreSystemTypes.Type; + case ElementType.Enum: return this.GetTypeFromSerializedName(ReadSerString(sigReader)); + } + throw new InvalidMetadataException(ExceptionStrings.MalformedSignature); + } + private FunctionPointer/*!*/ ParseFunctionPointer(MemoryCursor/*!*/ sigReader) + { + CallingConventionFlags convention = (CallingConventionFlags)sigReader.ReadByte(); + int n = sigReader.ReadCompressedInt(); + TypeNode returnType = this.ParseTypeSignature(sigReader); + if (returnType == null) returnType = CoreSystemTypes.Object; + TypeNodeList parameterTypes = new TypeNodeList(n); + int m = n; + for (int i = 0; i < n; i++) + { + TypeNode t = this.ParseTypeSignature(sigReader); + if (t == null) + m = i--; + else + parameterTypes.Add(t); + } + FunctionPointer fp = FunctionPointer.For(parameterTypes, returnType); + fp.CallingConvention = convention; + fp.VarArgStart = m; + return fp; + } + private StatementList ParseMethodBody(Method/*!*/ method, int methodIndex, int RVA) + { + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + if (method.DeclaringType.Template != null) + this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateArguments; + else + this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateParameters; + BodyParser parser = new BodyParser(this, method, methodIndex, RVA); + StatementList result = parser.ParseStatements(); + this.currentTypeParameters = savedCurrentTypeParameters; + return result; + } + private InstructionList ParseMethodInstructions(Method/*!*/ method, int methodIndex, int RVA) + { + TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters; + if (method.DeclaringType.Template != null) + this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateArguments; + else + this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateParameters; + InstructionParser parser = new InstructionParser(this, method, methodIndex, RVA); + InstructionList result = parser.ParseInstructions(); + this.currentTypeParameters = savedCurrentTypeParameters; + return result; + } + } + + internal abstract class ILParser + { + internal int counter; + protected Reader/*!*/ reader; + protected MemoryCursor/*!*/ bodyReader; + internal int size; + protected Method/*!*/ method; + protected int methodIndex; + protected int RVA; + protected LocalList/*!*/ locals = new LocalList(); + + internal ILParser(Reader/*!*/ reader, Method/*!*/ method, int methodIndex, int RVA) + { + this.reader = reader; + this.bodyReader = reader.tables.GetNewCursor(); + this.method = method; +#if !FxCop + this.method.LocalList = this.locals; +#else + this.method.Locals = this.locals; +#endif + this.methodIndex = methodIndex; + this.RVA = RVA; + //^ base(); + } + protected Expression Parameters(int i) + { + if (this.method.IsStatic) return this.method.Parameters[i]; + if (i == 0) return this.method.ThisParameter; + return this.method.Parameters[i - 1]; + } + protected void ParseHeader() + { + byte header = this.reader.tables.GetMethodBodyHeaderByte(this.RVA); + if ((header & 0x3) == 2) + { + this.size = header >> 2; + this.bodyReader = this.reader.tables.GetNewCursor(); + this.reader.tables.Skip(size); + } + else + { + method.InitLocals = (header & 0x10) != 0; + byte header2 = this.reader.tables.GetByte(); + int fatHeaderSize = header2 >> 4; + if (fatHeaderSize == 2) return; + if (fatHeaderSize != 3) throw new InvalidMetadataException(ExceptionStrings.InvalidFatMethodHeader); + this.reader.tables.Skip(2); //Skip over maxstack. No need to remember it. + this.size = this.reader.tables.GetInt32(); + int localIndex = this.reader.tables.GetInt32(); + this.bodyReader = this.reader.tables.GetNewCursor(); + this.reader.tables.Skip(size); + this.reader.tables.AlignTo32BitBoundary(); + while ((header & 0x8) != 0) + { + header = this.reader.tables.GetByte(); + if ((header & 3) != 1) throw new InvalidMetadataException(ExceptionStrings.BadMethodHeaderSection); + if ((header & 0x80) != 0) throw new InvalidMetadataException(ExceptionStrings.TooManyMethodHeaderSections); + this.ParseExceptionHandlerEntry((header & 0x40) == 0); + } + Hashtable localSourceNames = new Hashtable(); +#if UseSingularityPDB + if (this.reader.getDebugSymbols && this.reader.pdbFunctions != null) { + PdbFunction pdbFunc = this.reader.GetPdbFunction(0x6000000|(uint)methodIndex); + if (pdbFunc != null) + this.GetLocalNames(pdbFunc.scopes, localSourceNames); + } +#elif !ROTOR + if (this.reader.getDebugSymbols && this.reader.debugReader != null) + { + ISymUnmanagedMethod methodInfo = null; + try + { + try + { + this.reader.debugReader.GetMethod(0x6000000 | (uint)methodIndex, ref methodInfo); + if (methodInfo != null) + { + ISymUnmanagedScope rootScope = methodInfo.GetRootScope(); + try + { + this.reader.GetLocalSourceNames(rootScope, localSourceNames); + } + finally + { + if (rootScope != null) + Marshal.ReleaseComObject(rootScope); + } + } + } + catch (COMException) + { + } + catch (InvalidCastException) + { + } + catch (System.Runtime.InteropServices.InvalidComObjectException) { } + } + finally + { + if (methodInfo != null) + Marshal.ReleaseComObject(methodInfo); + } + } +#endif + this.reader.GetLocals(localIndex, this.locals, localSourceNames); + } + } + +#if UseSingularityPDB + private void GetLocalNames(PdbScope[] scopes, Hashtable localSourceNames) { + for (int i = 0, n = scopes == null ? 0 : scopes.Length; i < n; i++) { + PdbScope scope = scopes[i]; + foreach (PdbSlot slot in scope.slots) + localSourceNames[(int)slot.slot] = slot.name; + this.GetLocalNames(scope.scopes, localSourceNames); + } + } +#endif + + abstract protected void ParseExceptionHandlerEntry(bool smallSection); + protected byte GetByte() + { + this.counter += 1; + return this.bodyReader.ReadByte(); + } + protected sbyte GetSByte() + { + this.counter += 1; + return this.bodyReader.ReadSByte(); + } + protected short GetInt16() + { + this.counter += 2; + return this.bodyReader.ReadInt16(); + } + protected int GetInt32() + { + this.counter += 4; + return this.bodyReader.ReadInt32(); + } + protected long GetInt64() + { + this.counter += 8; + return this.bodyReader.ReadInt64(); + } + protected float GetSingle() + { + this.counter += 4; + return this.bodyReader.ReadSingle(); + } + protected double GetDouble() + { + this.counter += 8; + return this.bodyReader.ReadDouble(); + } + protected Member/*!*/ GetMemberFromToken() + { + return this.reader.GetMemberFromToken(this.GetInt32()); + } + protected Member/*!*/ GetMemberFromToken(out TypeNodeList varArgTypes) + { + return this.reader.GetMemberFromToken(this.GetInt32(), out varArgTypes); + } + protected string/*!*/ GetStringFromToken() + { + int tok = this.GetInt32(); + return this.reader.tables.GetUserString(tok & 0xFFFFFF); + } + protected OpCode GetOpCode() + { + int result = this.GetByte(); + if (result == (int)OpCode.Prefix1) + result = result << 8 | this.GetByte(); + return (OpCode)result; + } + } + sealed internal class BodyParser : ILParser + { + private readonly ExpressionStack/*!*/ operandStack = new ExpressionStack(); + private readonly TrivialHashtable/*!*/ blockMap = new TrivialHashtable(); + private int alignment = -1; + private bool isReadOnly; + private bool isTailCall; + private bool isVolatile; + private TypeNode constraint; + + internal BodyParser(Reader/*!*/ reader, Method/*!*/ method, int methodIndex, int RVA) + : base(reader, method, methodIndex, RVA) + { + //^ base; + } +#if !FxCop + override protected void ParseExceptionHandlerEntry(bool smallSection) + { + int dataSize = this.reader.tables.GetByte(); + int n = (int)(ushort)this.reader.tables.GetInt16(); + if (smallSection) + n = dataSize / 12; + else + n = (dataSize + (n << 8)) / 24; + if (n < 0) n = 0; + this.method.ExceptionHandlers = new ExceptionHandlerList(n); + for (int i = 0; i < n; i++) + { + int flags, tryOffset, tryLength, handlerOffset, handlerLength, tokenOrOffset; + if (smallSection) + { + flags = this.reader.tables.GetInt16(); + tryOffset = this.reader.tables.GetUInt16(); + tryLength = this.reader.tables.GetByte(); + handlerOffset = this.reader.tables.GetUInt16(); + handlerLength = this.reader.tables.GetByte(); + } + else + { + flags = this.reader.tables.GetInt32(); + tryOffset = this.reader.tables.GetInt32(); + tryLength = this.reader.tables.GetInt32(); + handlerOffset = this.reader.tables.GetInt32(); + handlerLength = this.reader.tables.GetInt32(); + } + tokenOrOffset = this.reader.tables.GetInt32(); + ExceptionHandler eh = new ExceptionHandler(); + switch (flags) + { + case 0x00: + eh.HandlerType = NodeType.Catch; + int pos = this.reader.tables.GetCurrentPosition(); + eh.FilterType = (TypeNode)this.reader.GetMemberFromToken(tokenOrOffset); + this.reader.tables.SetCurrentPosition(pos); + break; + case 0x01: + eh.HandlerType = NodeType.Filter; + eh.FilterExpression = Reader.GetOrCreateBlock(blockMap, tokenOrOffset); + break; + case 0x02: eh.HandlerType = NodeType.Finally; break; + case 0x04: eh.HandlerType = NodeType.FaultHandler; break; + default: throw new InvalidMetadataException(ExceptionStrings.BadExceptionHandlerType); + } + eh.TryStartBlock = Reader.GetOrCreateBlock(this.blockMap, tryOffset); + eh.BlockAfterTryEnd = Reader.GetOrCreateBlock(this.blockMap, tryOffset + tryLength); + eh.HandlerStartBlock = Reader.GetOrCreateBlock(this.blockMap, handlerOffset); + eh.BlockAfterHandlerEnd = Reader.GetOrCreateBlock(this.blockMap, handlerOffset + handlerLength); + this.method.ExceptionHandlers.Add(eh); + } + } +#endif + private AssignmentStatement/*!*/ ParseArrayElementAssignment(OpCode opCode) + { + Expression rhvalue = PopOperand(); + ExpressionList indexers = new ExpressionList(1); + indexers.Add(PopOperand()); + Expression array = PopOperand(); + Indexer indexer = new Indexer(array, indexers); + TypeNode t = CoreSystemTypes.Object; + switch (opCode) + { + case OpCode.Stelem_I: t = CoreSystemTypes.IntPtr; break; + case OpCode.Stelem_I1: t = CoreSystemTypes.Int8; break; + case OpCode.Stelem_I2: t = CoreSystemTypes.Int16; break; + case OpCode.Stelem_I4: t = CoreSystemTypes.Int32; break; + case OpCode.Stelem_I8: t = CoreSystemTypes.Int64; break; + case OpCode.Stelem_R4: t = CoreSystemTypes.Single; break; + case OpCode.Stelem_R8: t = CoreSystemTypes.Double; break; + case OpCode.Stelem: t = (TypeNode)this.GetMemberFromToken(); break; + default: + ArrayType arrT = array.Type as ArrayType; + if (arrT != null) t = arrT.ElementType; + break; + } + indexer.ElementType = indexer.Type = t; + return new AssignmentStatement(indexer, rhvalue); + } + private Indexer/*!*/ ParseArrayElementLoad(OpCode opCode, TypeNode elementType) + { + ExpressionList indexers = new ExpressionList(1); indexers.Add(PopOperand()); + Expression array = PopOperand(); + Indexer indexer = new Indexer(array, indexers); + TypeNode t = elementType; + switch (opCode) + { + case OpCode.Ldelem_I1: t = CoreSystemTypes.Int8; break; + case OpCode.Ldelem_U1: t = CoreSystemTypes.UInt8; break; + case OpCode.Ldelem_I2: t = CoreSystemTypes.Int16; break; + case OpCode.Ldelem_U2: t = CoreSystemTypes.UInt16; break; + case OpCode.Ldelem_I4: t = CoreSystemTypes.Int32; break; + case OpCode.Ldelem_U4: t = CoreSystemTypes.UInt32; break; + case OpCode.Ldelem_I8: t = CoreSystemTypes.Int64; break; + case OpCode.Ldelem_I: t = CoreSystemTypes.IntPtr; break; + case OpCode.Ldelem_R4: t = CoreSystemTypes.Single; break; + case OpCode.Ldelem_R8: t = CoreSystemTypes.Double; break; + case OpCode.Ldelem: t = (TypeNode)this.GetMemberFromToken(); break; + default: + if (t != null) break; + t = CoreSystemTypes.Object; + ArrayType arrT = array.Type as ArrayType; + if (arrT != null) t = arrT.ElementType; + break; + } + indexer.ElementType = indexer.Type = t; + return indexer; + } + private UnaryExpression/*!*/ ParseArrayElementLoadAddress() + { + TypeNode elemType = (TypeNode)this.GetMemberFromToken(); + return new UnaryExpression(this.ParseArrayElementLoad(0, elemType), this.isReadOnly ? NodeType.ReadOnlyAddressOf : NodeType.AddressOf, elemType.GetReferenceType()); + } + private static UnaryExpression/*!*/ SetType(UnaryExpression/*!*/ uex) + { + if (uex == null || uex.Operand == null) return uex; + TypeNode elemType = uex.Operand.Type; + if (elemType == null) return uex; + uex.Type = elemType.GetReferenceType(); + return uex; + } + private BinaryExpression/*!*/ ParseBinaryComparison(NodeType oper) + { + Expression op2 = PopOperand(); + Expression op1 = PopOperand(); + BinaryExpression result = new BinaryExpression(op1, op2, oper); + result.Type = CoreSystemTypes.Int32; + return result; + } + private BinaryExpression/*!*/ ParseBinaryOperation(NodeType oper) + { + Expression op2 = PopOperand(); + Expression op1 = PopOperand(); + BinaryExpression result = new BinaryExpression(op1, op2, oper); + result.Type = op1.Type; + if (result.Type == null) result.Type = op2.Type; + return result; + } + private UnaryExpression/*!*/ ParseUnaryOperation(NodeType oper) + { + Expression op = PopOperand(); + return new UnaryExpression(op, oper, op.Type); + } + private Branch/*!*/ ParseBranch(NodeType operatorType, int operandCount, bool shortOffset, bool unordered) + { + return this.ParseBranch(operatorType, operandCount, shortOffset, unordered, false); + } + private Branch/*!*/ ParseBranch(NodeType operatorType, int operandCount, bool shortOffset, bool unordered, bool leavesExceptionBlock) + { + Expression operand2 = operandCount > 1 ? PopOperand() : null; + Expression operand1 = operandCount > 0 ? PopOperand() : null; + Expression condition = operandCount > 1 ? (Expression)new BinaryExpression(operand1, operand2, operatorType) : + (operandCount > 0 ? (operatorType == NodeType.Nop ? operand1 : (Expression)new UnaryExpression(operand1, operatorType)) : null); + int targetAddress = shortOffset ? this.GetSByte() : this.GetInt32(); + Block targetBlock = (Block)this.blockMap[targetAddress + this.counter + 1]; + Debug.Assert(targetBlock != null); + if (targetAddress >= 0 && !this.reader.preserveShortBranches) shortOffset = false; + return new Branch(condition, targetBlock, shortOffset, unordered, leavesExceptionBlock); + } + private MethodCall/*!*/ ParseCall(NodeType typeOfCall, out bool isStatement) + { + TypeNodeList varArgTypes; + Method meth = (Method)this.GetMemberFromToken(out varArgTypes); + int numVarArgs = varArgTypes == null ? 0 : varArgTypes.Count; + isStatement = BodyParser.TypeIsVoid(meth.ReturnType); + int n = meth.Parameters == null ? 0 : meth.Parameters.Count; + if (typeOfCall == NodeType.Jmp) n = 0; + else n += numVarArgs; + Expression[] args = new Expression[n]; + ExpressionList arguments = new ExpressionList(n); + for (int i = n - 1; i >= 0; i--) args[i] = PopOperand(); + for (int i = 0; i < n; i++) arguments.Add(args[i]); + if (varArgTypes != null) + { + for (int i = n - 1, j = numVarArgs; j > 0; j--, i--) + { + Expression e = arguments[i]; + TypeNode t = varArgTypes[j - 1]; + if (e != null && t != null) e.Type = t; + } + } + Expression thisob = meth.IsStatic ? null : PopOperand(); + MemberBinding methBinding = new MemberBinding(thisob, meth); + MethodCall result = new MethodCall(methBinding, arguments, typeOfCall); + result.Type = meth.ReturnType; + result.IsTailCall = this.isTailCall; + if (this.constraint != null) + { + result.Constraint = this.constraint; + this.constraint = null; + } + return result; + } + private static bool TypeIsVoid(TypeNode t) + { + if (t == null) return false; + for (; ; ) + { + switch (t.NodeType) + { + case NodeType.OptionalModifier: + case NodeType.RequiredModifier: + t = ((TypeModifier)t).ModifiedType; + break; + default: + return t == CoreSystemTypes.Void; + } + } + } + private MethodCall/*!*/ ParseCalli(out bool isStatement) + { + FunctionPointer fp = this.reader.GetCalliSignature(this.GetInt32()); + if (fp == null) throw new InvalidMetadataException(ExceptionStrings.BaddCalliSignature); + isStatement = BodyParser.TypeIsVoid(fp.ReturnType); + int n = fp.ParameterTypes.Count; + Expression[] args = new Expression[n + 1]; + ExpressionList arguments = new ExpressionList(n + 1); + for (int i = n; i >= 0; i--) args[i] = PopOperand(); + for (int i = 0; i <= n; i++) arguments.Add(args[i]); + Expression thisob = fp.IsStatic ? null : PopOperand(); + MemberBinding methBinding = new MemberBinding(thisob, fp); + MethodCall result = new MethodCall(methBinding, arguments, NodeType.Calli); + result.Type = fp.ReturnType; + result.IsTailCall = this.isTailCall; + return result; + } + private static Expression/*!*/ ParseTypeCheck(Expression operand, TypeNode type, NodeType typeOfCheck) + { + TypeNode etype = type; + if (typeOfCheck == NodeType.Unbox) etype = type.GetReferenceType(); + Expression expr = new BinaryExpression(operand, new Literal(type, CoreSystemTypes.Type), typeOfCheck, etype); + return expr; + } + private Construct/*!*/ ParseConstruct() + { + TypeNodeList varArgTypes; + Method meth = (Method)this.GetMemberFromToken(out varArgTypes); + int n = meth.Parameters.Count; + Expression[] args = new Expression[n]; + ExpressionList arguments = new ExpressionList(n); + for (int i = n - 1; i >= 0; i--) args[i] = PopOperand(); + for (int i = 0; i < n; i++) arguments.Add(args[i]); + Construct result = new Construct(new MemberBinding(null, meth), arguments); + result.Type = meth.DeclaringType; + return result; + } + private AssignmentStatement/*!*/ ParseCopyObject() + { + TypeNode type = (TypeNode)this.GetMemberFromToken(); + Expression rhaddr = PopOperand(); + Expression lhaddr = PopOperand(); + return new AssignmentStatement(new AddressDereference(lhaddr, type, this.isVolatile, this.alignment), new AddressDereference(rhaddr, type)); + } + private UnaryExpression /*!*/ ParseLoadRuntimeMetadataToken() + { + Expression expr = null; + TypeNode exprType = null; + Member member = this.GetMemberFromToken(); + TypeNode t = member as TypeNode; + if (t == null) + { + exprType = (member.NodeType == NodeType.Field) + ? CoreSystemTypes.RuntimeFieldHandle : CoreSystemTypes.RuntimeMethodHandle; + expr = new MemberBinding(null, member); + } + else + { + exprType = CoreSystemTypes.RuntimeTypeHandle; + expr = new Literal(t, CoreSystemTypes.Type); + } + return new UnaryExpression(expr, NodeType.Ldtoken, exprType); + } + private AssignmentStatement/*!*/ ParseInitObject() + { + TypeNode type = (TypeNode)this.GetMemberFromToken(); + Expression lhaddr = PopOperand(); + return new AssignmentStatement(new AddressDereference(lhaddr, type, this.isVolatile, this.alignment), new Literal(null, CoreSystemTypes.Object)); + } + private ConstructArray/*!*/ ParseNewArray() + { + TypeNode type = (TypeNode)this.GetMemberFromToken(); + ExpressionList sizes = new ExpressionList(1); + sizes.Add(PopOperand()); + ConstructArray result = new ConstructArray(type, sizes, null); + result.Type = type.GetArrayType(1); + return result; + } +#if !FxCop + internal StatementList/*!*/ ParseStatements() + { + this.ParseHeader(); + if (this.size == 0) return new StatementList(0); + this.CreateBlocksForBranchTargets(); + StatementList result = new StatementList(); + Block currentBlock = null; + while (this.counter < size) + { + if (currentBlock == null) + { + currentBlock = Reader.GetOrCreateBlock(this.blockMap, this.counter); + result.Add(currentBlock); + } + bool endOfBasicBlock = this.ParseStatement(currentBlock); + if (endOfBasicBlock) currentBlock = null; + } + result.Add(Reader.GetOrCreateBlock(this.blockMap, this.counter)); + return result; + } +#endif + private bool ParseStatement(Block/*!*/ block) + { + //parse instructions and put in expression tree until an assignment, void call, branch target, or branch is encountered + StatementList statementList = block.Statements; + Expression expr = null; + Statement statement = null; + bool transferStatement = false; + int startingAddress = 0; +#if !FxCop + SourceContext sourceContext = new SourceContext(); + sourceContext.StartPos = this.counter; +#endif +#if !ROTOR + if (this.method.contextForOffset != null) + { + object sctx = this.method.contextForOffset[this.counter + 1]; + if (sctx != null) sourceContext = (SourceContext)sctx; + } +#endif + while (true) + { + bool isStatement = false; + startingAddress = this.counter + 1; //Add one so that it is never zero (the latter means no entry to the TrivialHashtable) +#if !FxCop + OpCode opCode = this.GetOpCode(); +#else + this.ilOffset = this.counter; + if (this.handlerMap.TryGetValue(this.ilOffset, out expr)){ + expr.sourceContext = sourceContext; + expr.ILOffset = this.ilOffset; + this.operandStack.Push(expr); + } + this.opCode = this.GetOpCode(); +#endif + switch (opCode) + { + case OpCode.Nop: statement = new Statement(NodeType.Nop); goto done; + case OpCode.Break: statement = new Statement(NodeType.DebugBreak); goto done; + case OpCode.Ldarg_0: expr = this.Parameters(0); break; + case OpCode.Ldarg_1: expr = this.Parameters(1); break; + case OpCode.Ldarg_2: expr = this.Parameters(2); break; + case OpCode.Ldarg_3: expr = this.Parameters(3); break; + case OpCode.Ldloc_0: expr = this.locals[0]; break; + case OpCode.Ldloc_1: expr = this.locals[1]; break; + case OpCode.Ldloc_2: expr = this.locals[2]; break; + case OpCode.Ldloc_3: expr = this.locals[3]; break; + case OpCode.Stloc_0: statement = new AssignmentStatement(this.locals[0], PopOperand()); goto done; + case OpCode.Stloc_1: statement = new AssignmentStatement(this.locals[1], PopOperand()); goto done; + case OpCode.Stloc_2: statement = new AssignmentStatement(this.locals[2], PopOperand()); goto done; + case OpCode.Stloc_3: statement = new AssignmentStatement(this.locals[3], PopOperand()); goto done; + case OpCode.Ldarg_S: expr = this.Parameters(this.GetByte()); break; + case OpCode.Ldarga_S: expr = SetType(new UnaryExpression(this.Parameters(this.GetByte()), NodeType.AddressOf)); break; + case OpCode.Starg_S: statement = new AssignmentStatement(this.Parameters(this.GetByte()), PopOperand()); goto done; + case OpCode.Ldloc_S: expr = this.locals[this.GetByte()]; break; + case OpCode.Ldloca_S: expr = SetType(new UnaryExpression(this.locals[this.GetByte()], NodeType.AddressOf)); break; + case OpCode.Stloc_S: statement = new AssignmentStatement(this.locals[this.GetByte()], PopOperand()); goto done; + case OpCode.Ldnull: expr = new Literal(null, CoreSystemTypes.Object); break; + case OpCode.Ldc_I4_M1: expr = new Literal(-1, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_0: expr = new Literal(0, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_1: expr = new Literal(1, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_2: expr = new Literal(2, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_3: expr = new Literal(3, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_4: expr = new Literal(4, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_5: expr = new Literal(5, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_6: expr = new Literal(6, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_7: expr = new Literal(7, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_8: expr = new Literal(8, CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4_S: expr = new Literal((int)this.GetSByte(), CoreSystemTypes.Int32); break; + case OpCode.Ldc_I4: expr = new Literal(this.GetInt32(), CoreSystemTypes.Int32); break; + case OpCode.Ldc_I8: expr = new Literal(this.GetInt64(), CoreSystemTypes.Int64); break; + case OpCode.Ldc_R4: expr = new Literal(this.GetSingle(), CoreSystemTypes.Single); break; + case OpCode.Ldc_R8: expr = new Literal(this.GetDouble(), CoreSystemTypes.Double); break; + case OpCode.Dup: statement = new ExpressionStatement(new Expression(NodeType.Dup)); goto done; + case OpCode.Pop: statement = new ExpressionStatement(new UnaryExpression(PopOperand(), NodeType.Pop)); goto done; + case OpCode.Jmp: expr = this.ParseCall(NodeType.Jmp, out isStatement); if (isStatement) goto done; break; + case OpCode.Call: expr = this.ParseCall(NodeType.Call, out isStatement); if (isStatement) goto done; break; + case OpCode.Calli: expr = this.ParseCalli(out isStatement); if (isStatement) goto done; break; + case OpCode.Ret: + Expression retVal = BodyParser.TypeIsVoid(this.method.ReturnType) ? null : PopOperand(); + statement = new Return(retVal); + transferStatement = true; goto done; + case OpCode.Br_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false); transferStatement = true; goto done; + case OpCode.Brfalse_S: statement = this.ParseBranch(NodeType.LogicalNot, 1, true, false); transferStatement = true; goto done; + case OpCode.Brtrue_S: statement = this.ParseBranch(NodeType.Nop, 1, true, false); transferStatement = true; goto done; + case OpCode.Beq_S: statement = this.ParseBranch(NodeType.Eq, 2, true, false); transferStatement = true; goto done; + case OpCode.Bge_S: statement = this.ParseBranch(NodeType.Ge, 2, true, false); transferStatement = true; goto done; + case OpCode.Bgt_S: statement = this.ParseBranch(NodeType.Gt, 2, true, false); transferStatement = true; goto done; + case OpCode.Ble_S: statement = this.ParseBranch(NodeType.Le, 2, true, false); transferStatement = true; goto done; + case OpCode.Blt_S: statement = this.ParseBranch(NodeType.Lt, 2, true, false); transferStatement = true; goto done; + case OpCode.Bne_Un_S: statement = this.ParseBranch(NodeType.Ne, 2, true, true); transferStatement = true; goto done; + case OpCode.Bge_Un_S: statement = this.ParseBranch(NodeType.Ge, 2, true, true); transferStatement = true; goto done; + case OpCode.Bgt_Un_S: statement = this.ParseBranch(NodeType.Gt, 2, true, true); transferStatement = true; goto done; + case OpCode.Ble_Un_S: statement = this.ParseBranch(NodeType.Le, 2, true, true); transferStatement = true; goto done; + case OpCode.Blt_Un_S: statement = this.ParseBranch(NodeType.Lt, 2, true, true); transferStatement = true; goto done; + case OpCode.Br: statement = this.ParseBranch(NodeType.Nop, 0, false, false); transferStatement = true; goto done; + case OpCode.Brfalse: statement = this.ParseBranch(NodeType.LogicalNot, 1, false, false); transferStatement = true; goto done; + case OpCode.Brtrue: statement = this.ParseBranch(NodeType.Nop, 1, false, false); transferStatement = true; goto done; + case OpCode.Beq: statement = this.ParseBranch(NodeType.Eq, 2, false, false); transferStatement = true; goto done; + case OpCode.Bge: statement = this.ParseBranch(NodeType.Ge, 2, false, false); transferStatement = true; goto done; + case OpCode.Bgt: statement = this.ParseBranch(NodeType.Gt, 2, false, false); transferStatement = true; goto done; + case OpCode.Ble: statement = this.ParseBranch(NodeType.Le, 2, false, false); transferStatement = true; goto done; + case OpCode.Blt: statement = this.ParseBranch(NodeType.Lt, 2, false, false); transferStatement = true; goto done; + case OpCode.Bne_Un: statement = this.ParseBranch(NodeType.Ne, 2, false, true); transferStatement = true; goto done; + case OpCode.Bge_Un: statement = this.ParseBranch(NodeType.Ge, 2, false, true); transferStatement = true; goto done; + case OpCode.Bgt_Un: statement = this.ParseBranch(NodeType.Gt, 2, false, true); transferStatement = true; goto done; + case OpCode.Ble_Un: statement = this.ParseBranch(NodeType.Le, 2, false, true); transferStatement = true; goto done; + case OpCode.Blt_Un: statement = this.ParseBranch(NodeType.Lt, 2, false, true); transferStatement = true; goto done; + case OpCode.Switch: statement = this.ParseSwitchInstruction(); transferStatement = true; goto done; + case OpCode.Ldind_I1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int8, this.isVolatile, this.alignment); break; + case OpCode.Ldind_U1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt8, this.isVolatile, this.alignment); break; + case OpCode.Ldind_I2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int16, this.isVolatile, this.alignment); break; + case OpCode.Ldind_U2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt16, this.isVolatile, this.alignment); break; + case OpCode.Ldind_I4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int32, this.isVolatile, this.alignment); break; + case OpCode.Ldind_U4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt32, this.isVolatile, this.alignment); break; + case OpCode.Ldind_I8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int64, this.isVolatile, this.alignment); break; + case OpCode.Ldind_I: expr = new AddressDereference(PopOperand(), CoreSystemTypes.IntPtr, this.isVolatile, this.alignment); break; + case OpCode.Ldind_R4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Single, this.isVolatile, this.alignment); break; + case OpCode.Ldind_R8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Double, this.isVolatile, this.alignment); break; + case OpCode.Ldind_Ref: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Object, this.isVolatile, this.alignment); break; + case OpCode.Stind_Ref: statement = this.ParseStoreIndirect(CoreSystemTypes.Object); goto done; + case OpCode.Stind_I1: statement = this.ParseStoreIndirect(CoreSystemTypes.Int8); goto done; + case OpCode.Stind_I2: statement = this.ParseStoreIndirect(CoreSystemTypes.Int16); goto done; + case OpCode.Stind_I4: statement = this.ParseStoreIndirect(CoreSystemTypes.Int32); goto done; + case OpCode.Stind_I8: statement = this.ParseStoreIndirect(CoreSystemTypes.Int64); goto done; + case OpCode.Stind_R4: statement = this.ParseStoreIndirect(CoreSystemTypes.Single); goto done; + case OpCode.Stind_R8: statement = this.ParseStoreIndirect(CoreSystemTypes.Double); goto done; + case OpCode.Add: expr = this.ParseBinaryOperation(NodeType.Add); break; + case OpCode.Sub: expr = this.ParseBinaryOperation(NodeType.Sub); break; + case OpCode.Mul: expr = this.ParseBinaryOperation(NodeType.Mul); break; + case OpCode.Div: expr = this.ParseBinaryOperation(NodeType.Div); break; + case OpCode.Div_Un: expr = this.ParseBinaryOperation(NodeType.Div_Un); break; + case OpCode.Rem: expr = this.ParseBinaryOperation(NodeType.Rem); break; + case OpCode.Rem_Un: expr = this.ParseBinaryOperation(NodeType.Rem_Un); break; + case OpCode.And: expr = this.ParseBinaryOperation(NodeType.And); break; + case OpCode.Or: expr = this.ParseBinaryOperation(NodeType.Or); break; + case OpCode.Xor: expr = this.ParseBinaryOperation(NodeType.Xor); break; + case OpCode.Shl: expr = this.ParseBinaryOperation(NodeType.Shl); break; + case OpCode.Shr: expr = this.ParseBinaryOperation(NodeType.Shr); break; + case OpCode.Shr_Un: expr = this.ParseBinaryOperation(NodeType.Shr_Un); break; + case OpCode.Neg: expr = this.ParseUnaryOperation(NodeType.Neg); break; + case OpCode.Not: expr = this.ParseUnaryOperation(NodeType.Not); break; + case OpCode.Conv_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I1, CoreSystemTypes.Int8); break; + case OpCode.Conv_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I2, CoreSystemTypes.Int16); break; + case OpCode.Conv_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I4, CoreSystemTypes.Int32); break; + case OpCode.Conv_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I8, CoreSystemTypes.Int64); break; + case OpCode.Conv_R4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R4, CoreSystemTypes.Single); break; + case OpCode.Conv_R8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R8, CoreSystemTypes.Double); break; + case OpCode.Conv_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U4, CoreSystemTypes.UInt32); break; + case OpCode.Conv_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U8, CoreSystemTypes.UInt64); break; + case OpCode.Callvirt: expr = this.ParseCall(NodeType.Callvirt, out isStatement); if (isStatement) goto done; break; + case OpCode.Cpobj: statement = this.ParseCopyObject(); goto done; + case OpCode.Ldobj: expr = new AddressDereference(PopOperand(), (TypeNode)this.GetMemberFromToken(), this.isVolatile, this.alignment); break; + case OpCode.Ldstr: expr = new Literal(this.GetStringFromToken(), CoreSystemTypes.String); break; + case OpCode.Newobj: expr = this.ParseConstruct(); break; + case OpCode.Castclass: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Castclass); break; + case OpCode.Isinst: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Isinst); break; + case OpCode.Conv_R_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R_Un, CoreSystemTypes.Double); break; + case OpCode.Unbox: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Unbox); break; + case OpCode.Throw: statement = new Throw(PopOperand()); transferStatement = true; goto done; + case OpCode.Ldfld: + expr = new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment); + break; + case OpCode.Ldflda: + expr = SetType(new UnaryExpression(new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); + break; + case OpCode.Stfld: statement = this.ParseStoreField(); goto done; + case OpCode.Ldsfld: expr = new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment); break; + case OpCode.Ldsflda: expr = SetType(new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break; + case OpCode.Stsfld: statement = new AssignmentStatement(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), PopOperand()); goto done; + case OpCode.Stobj: statement = this.ParseStoreIndirect((TypeNode)this.GetMemberFromToken()); goto done; + case OpCode.Conv_Ovf_I1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1_Un, CoreSystemTypes.Int8); break; + case OpCode.Conv_Ovf_I2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2_Un, CoreSystemTypes.Int16); break; + case OpCode.Conv_Ovf_I4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4_Un, CoreSystemTypes.Int32); break; + case OpCode.Conv_Ovf_I8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8_Un, CoreSystemTypes.Int64); break; + case OpCode.Conv_Ovf_U1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1_Un, CoreSystemTypes.UInt8); break; + case OpCode.Conv_Ovf_U2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2_Un, CoreSystemTypes.UInt16); break; + case OpCode.Conv_Ovf_U4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4_Un, CoreSystemTypes.UInt32); break; + case OpCode.Conv_Ovf_U8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8_Un, CoreSystemTypes.UInt64); break; + case OpCode.Conv_Ovf_I_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I_Un, CoreSystemTypes.IntPtr); break; + case OpCode.Conv_Ovf_U_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U_Un, CoreSystemTypes.UIntPtr); break; + case OpCode.Box: + TypeNode t = (TypeNode)this.GetMemberFromToken(); + TypeNode bt = t is EnumNode ? CoreSystemTypes.Enum : CoreSystemTypes.ValueType; + expr = new BinaryExpression(PopOperand(), new Literal(t, CoreSystemTypes.Type), NodeType.Box, bt); break; + case OpCode.Newarr: expr = this.ParseNewArray(); break; + case OpCode.Ldlen: expr = new UnaryExpression(PopOperand(), NodeType.Ldlen, CoreSystemTypes.UIntPtr); break; + case OpCode.Ldelema: expr = this.ParseArrayElementLoadAddress(); break; + case OpCode.Ldelem_I1: + case OpCode.Ldelem_U1: + case OpCode.Ldelem_I2: + case OpCode.Ldelem_U2: + case OpCode.Ldelem_I4: + case OpCode.Ldelem_U4: + case OpCode.Ldelem_I8: + case OpCode.Ldelem_I: + case OpCode.Ldelem_R4: + case OpCode.Ldelem_R8: + case OpCode.Ldelem_Ref: expr = this.ParseArrayElementLoad(opCode, null); break; + case OpCode.Stelem_I: + case OpCode.Stelem_I1: + case OpCode.Stelem_I2: + case OpCode.Stelem_I4: + case OpCode.Stelem_I8: + case OpCode.Stelem_R4: + case OpCode.Stelem_R8: + case OpCode.Stelem_Ref: statement = this.ParseArrayElementAssignment(opCode); goto done; + case OpCode.Ldelem: expr = this.ParseArrayElementLoad(opCode, null); break; + case OpCode.Stelem: statement = this.ParseArrayElementAssignment(opCode); goto done; + case OpCode.Unbox_Any: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.UnboxAny); break; + case OpCode.Conv_Ovf_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1, CoreSystemTypes.Int8); break; + case OpCode.Conv_Ovf_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1, CoreSystemTypes.UInt8); break; + case OpCode.Conv_Ovf_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2, CoreSystemTypes.Int16); break; + case OpCode.Conv_Ovf_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2, CoreSystemTypes.UInt16); break; + case OpCode.Conv_Ovf_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4, CoreSystemTypes.Int32); break; + case OpCode.Conv_Ovf_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4, CoreSystemTypes.UInt32); break; + case OpCode.Conv_Ovf_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8, CoreSystemTypes.Int64); break; + case OpCode.Conv_Ovf_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8, CoreSystemTypes.UInt64); break; + case OpCode.Refanyval: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Refanyval, CoreSystemTypes.IntPtr); break; + case OpCode.Ckfinite: expr = this.ParseUnaryOperation(NodeType.Ckfinite); break; + case OpCode.Mkrefany: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Mkrefany, CoreSystemTypes.DynamicallyTypedReference); break; + case OpCode.Ldtoken: expr = ParseLoadRuntimeMetadataToken(); break; + case OpCode.Conv_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U2, CoreSystemTypes.UInt16); break; + case OpCode.Conv_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U1, CoreSystemTypes.UInt8); break; + case OpCode.Conv_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I, CoreSystemTypes.IntPtr); break; + case OpCode.Conv_Ovf_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I, CoreSystemTypes.IntPtr); break; + case OpCode.Conv_Ovf_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U, CoreSystemTypes.UIntPtr); break; + case OpCode.Add_Ovf: expr = this.ParseBinaryOperation(NodeType.Add_Ovf); break; + case OpCode.Add_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Add_Ovf_Un); break; + case OpCode.Mul_Ovf: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf); break; + case OpCode.Mul_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf_Un); break; + case OpCode.Sub_Ovf: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf); break; + case OpCode.Sub_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf_Un); break; + case OpCode.Endfinally: statement = new EndFinally(); transferStatement = true; goto done; + case OpCode.Leave: statement = this.ParseBranch(NodeType.Nop, 0, false, false, true); transferStatement = true; goto done; + case OpCode.Leave_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false, true); transferStatement = true; goto done; + case OpCode.Stind_I: statement = this.ParseStoreIndirect(CoreSystemTypes.IntPtr); goto done; + case OpCode.Conv_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U, CoreSystemTypes.UIntPtr); break; + case OpCode.Arglist: expr = new Expression(NodeType.Arglist, CoreSystemTypes.ArgIterator); break; + case OpCode.Ceq: expr = this.ParseBinaryComparison(NodeType.Ceq); break; + case OpCode.Cgt: expr = this.ParseBinaryComparison(NodeType.Cgt); break; + case OpCode.Cgt_Un: expr = this.ParseBinaryComparison(NodeType.Cgt_Un); break; + case OpCode.Clt: expr = this.ParseBinaryComparison(NodeType.Clt); break; + case OpCode.Clt_Un: expr = this.ParseBinaryComparison(NodeType.Clt_Un); break; + case OpCode.Ldftn: expr = new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldftn, CoreSystemTypes.IntPtr); break; + case OpCode.Ldvirtftn: expr = new BinaryExpression(PopOperand(), new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldvirtftn, CoreSystemTypes.IntPtr); break; + case OpCode.Ldarg: expr = this.Parameters((ushort)this.GetInt16()); break; + case OpCode.Ldarga: expr = SetType(new UnaryExpression(this.Parameters((ushort)this.GetInt16()), NodeType.AddressOf)); break; + case OpCode.Starg: statement = new AssignmentStatement(this.Parameters((ushort)this.GetInt16()), PopOperand()); goto done; + case OpCode.Ldloc: expr = this.locals[(ushort)this.GetInt16()]; break; + case OpCode.Ldloca: expr = SetType(new UnaryExpression(this.locals[(ushort)this.GetInt16()], NodeType.AddressOf)); break; + case OpCode.Stloc: statement = new AssignmentStatement(this.locals[(ushort)this.GetInt16()], PopOperand()); goto done; + case OpCode.Localloc: expr = new UnaryExpression(PopOperand(), NodeType.Localloc, CoreSystemTypes.Void); break; + case OpCode.Endfilter: statement = new EndFilter(PopOperand()); transferStatement = true; goto done; + case OpCode.Unaligned_: this.alignment = this.GetByte(); continue; + case OpCode.Volatile_: this.isVolatile = true; continue; + case OpCode.Tail_: this.isTailCall = true; continue; + case OpCode.Initobj: statement = this.ParseInitObject(); goto done; + case OpCode.Constrained_: this.constraint = this.GetMemberFromToken() as TypeNode; continue; + case OpCode.Cpblk: expr = this.ParseTernaryOperation(NodeType.Cpblk); goto done; + case OpCode.Initblk: expr = this.ParseTernaryOperation(NodeType.Initblk); goto done; + case OpCode.Rethrow: statement = new Throw(null); statement.NodeType = NodeType.Rethrow; transferStatement = true; goto done; + case OpCode.Sizeof: expr = new UnaryExpression(new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Sizeof, CoreSystemTypes.Int32); break; + case OpCode.Refanytype: expr = new UnaryExpression(PopOperand(), NodeType.Refanytype, CoreSystemTypes.RuntimeTypeHandle); break; + case OpCode.Readonly_: this.isReadOnly = true; continue; + default: throw new InvalidMetadataException(ExceptionStrings.UnknownOpCode); + } + if (this.blockMap[this.counter + 1] != null) + { + transferStatement = true; //Falls through to the next basic block, so implicitly a "transfer" statement + goto done; + } + //^ assume expr != null; +#if FxCop + expr.sourceContext = sourceContext; + expr.ILOffset = this.ilOffset; +#endif + this.operandStack.Push(expr); + this.isReadOnly = false; + this.isVolatile = false; + this.isTailCall = false; + this.alignment = -1; + } + done: + for (int i = 0; i <= this.operandStack.top; i++) + { + Expression e = this.operandStack.elements[i]; + //^ assume e != null; + Statement s = new ExpressionStatement(e); +#if FxCop + s.SourceContext = this.sourceContext; + s.ILOffset = this.ilOffset; +#endif + statementList.Add(s); + } + this.operandStack.top = -1; + if (statement == null) + { + statement = new ExpressionStatement(expr); +#if FxCop + expr.SourceContext = this.sourceContext; + expr.ILOffset = this.ilOffset; +#endif + } + statement.SourceContext = sourceContext; +#if FxCop + statement.ILOffset = this.ilOffset; +#endif + statementList.Add(statement); + if (transferStatement) return true; + return this.blockMap[this.counter + 1] != null; + } + private AssignmentStatement ParseStoreField() + { + Expression rhvalue = PopOperand(); + Expression thisob = PopOperand(); + AssignmentStatement s = new AssignmentStatement(new MemberBinding(thisob, this.GetMemberFromToken(), this.isVolatile, this.alignment), rhvalue); + return s; + } + private AssignmentStatement ParseStoreIndirect(TypeNode type) + { + Expression rhvalue = PopOperand(); + Expression lhaddr = PopOperand(); + return new AssignmentStatement(new AddressDereference(lhaddr, type, this.isVolatile, this.alignment), rhvalue); + } + private SwitchInstruction ParseSwitchInstruction() + { + int numTargets = this.GetInt32(); + int offset = this.counter + numTargets * 4; + BlockList targetList = new BlockList(numTargets); + for (int i = 0; i < numTargets; i++) + { + int targetAddress = this.GetInt32() + offset; + targetList.Add(Reader.GetOrCreateBlock(this.blockMap, targetAddress)); + } + return new SwitchInstruction(PopOperand(), targetList); + } + private TernaryExpression ParseTernaryOperation(NodeType oper) + { + Expression op3 = PopOperand(); + Expression op2 = PopOperand(); + Expression op1 = PopOperand(); + return new TernaryExpression(op1, op2, op3, oper, null); + } + private void CreateBlocksForBranchTargets() + { + int savedPosition = bodyReader.Position; + while (this.counter < this.size) + this.ProcessOneILInstruction(); + this.counter = 0; + bodyReader.Position = savedPosition; + } + private void ProcessOneILInstruction() + { + OpCode opc = this.GetOpCode(); + switch (opc) + { + case OpCode.Ldarg_S: + case OpCode.Ldarga_S: + case OpCode.Starg_S: + case OpCode.Ldloc_S: + case OpCode.Ldloca_S: + case OpCode.Stloc_S: + case OpCode.Ldc_I4_S: + this.GetByte(); return; + case OpCode.Ldc_I4: + case OpCode.Jmp: + case OpCode.Call: + case OpCode.Calli: + case OpCode.Callvirt: + case OpCode.Cpobj: + case OpCode.Ldobj: + case OpCode.Ldstr: + case OpCode.Newobj: + case OpCode.Castclass: + case OpCode.Isinst: + case OpCode.Unbox: + case OpCode.Ldfld: + case OpCode.Ldflda: + case OpCode.Stfld: + case OpCode.Ldsfld: + case OpCode.Ldsflda: + case OpCode.Stsfld: + case OpCode.Stobj: + case OpCode.Box: + case OpCode.Newarr: + case OpCode.Ldelema: + case OpCode.Ldelem: + case OpCode.Stelem: + case OpCode.Unbox_Any: + case OpCode.Refanyval: + case OpCode.Mkrefany: + case OpCode.Ldtoken: + this.GetInt32(); return; + case OpCode.Ldc_I8: + this.GetInt64(); return; + case OpCode.Ldc_R4: + this.GetSingle(); return; + case OpCode.Ldc_R8: + this.GetDouble(); return; + case OpCode.Br_S: + case OpCode.Brfalse_S: + case OpCode.Brtrue_S: + case OpCode.Beq_S: + case OpCode.Bge_S: + case OpCode.Bgt_S: + case OpCode.Ble_S: + case OpCode.Blt_S: + case OpCode.Bne_Un_S: + case OpCode.Bge_Un_S: + case OpCode.Bgt_Un_S: + case OpCode.Ble_Un_S: + case OpCode.Blt_Un_S: + case OpCode.Leave_S: + this.SkipBranch(true); return; + case OpCode.Br: + case OpCode.Brfalse: + case OpCode.Brtrue: + case OpCode.Beq: + case OpCode.Bge: + case OpCode.Bgt: + case OpCode.Ble: + case OpCode.Blt: + case OpCode.Bne_Un: + case OpCode.Bge_Un: + case OpCode.Bgt_Un: + case OpCode.Ble_Un: + case OpCode.Blt_Un: + case OpCode.Leave: + this.SkipBranch(false); return; + case OpCode.Switch: + this.SkipSwitch(); return; + case OpCode.Ldftn: + case OpCode.Ldvirtftn: + case OpCode.Initobj: + case OpCode.Constrained_: + case OpCode.Sizeof: + this.GetInt32(); return; + case OpCode.Ldarg: + case OpCode.Ldarga: + case OpCode.Ldloc: + case OpCode.Ldloca: + case OpCode.Starg: + case OpCode.Stloc: + this.GetInt16(); return; + case OpCode.Unaligned_: + this.GetByte(); return; + default: + return; + } + } + private void SkipBranch(bool shortOffset) + { + int offset = shortOffset ? this.GetSByte() : this.GetInt32(); + Reader.GetOrCreateBlock(blockMap, this.counter + offset); + } + private void SkipSwitch() + { + int numCases = this.GetInt32(); + int offset = this.counter + numCases * 4; + for (int i = 0; i < numCases; i++) + { + int targetAddress = this.GetInt32() + offset; + Reader.GetOrCreateBlock(this.blockMap, targetAddress); + } + } + private Expression PopOperand() + { + return this.operandStack.Pop(); + } +#if FxCop + private OpCode opCode; + private Block currentBlock; + private SourceContext sourceContext; + private int ilOffset; + private Dictionary<Block, List<TryNode>> tryMap; + private Dictionary<int, Expression> handlerMap; + internal StatementList/*!*/ ParseStatements() { + this.tryMap = new Dictionary<Block, List<TryNode>>(); + this.handlerMap = new Dictionary<int, Expression>(); + this.ParseHeader(); + this.CreateBlocksForBranchTargets(); + currentBlock = null; + this.sourceContext = new SourceContext(); + while (this.counter < size) { + if (currentBlock == null) { + currentBlock = Reader.GetOrCreateBlock(this.blockMap, this.counter); + } + bool endOfBasicBlock = this.ParseStatement(currentBlock); + if (endOfBasicBlock) { + currentBlock.SourceContext = currentBlock.Statements[0].SourceContext; + currentBlock = null; + } + } + Reader.GetOrCreateBlock(this.blockMap, this.counter); + int counter = 0; + Block block = new Block(); + block.Statements = new StatementList(); + ProcessBlock(block, ref counter, this.size, null); + return block.Statements; + } + override protected void ParseExceptionHandlerEntry(bool smallSection) { + int dataSize = this.reader.tables.GetByte(); + int n = (int)(ushort)this.reader.tables.GetInt16(); + if (smallSection) + n = dataSize / 12; + else + n = (dataSize + (n << 8)) / 24; + for (int i = 0; i < n; i++) { + int flags, tryOffset, tryLength, handlerOffset, handlerLength, tokenOrOffset; + if (smallSection) { + flags = this.reader.tables.GetInt16(); + tryOffset = this.reader.tables.GetUInt16(); + tryLength = this.reader.tables.GetByte(); + handlerOffset = this.reader.tables.GetUInt16(); + handlerLength = this.reader.tables.GetByte(); + } + else { + flags = this.reader.tables.GetInt32(); + tryOffset = this.reader.tables.GetInt32(); + tryLength = this.reader.tables.GetInt32(); + handlerOffset = this.reader.tables.GetInt32(); + handlerLength = this.reader.tables.GetInt32(); + } + tokenOrOffset = this.reader.tables.GetInt32(); + Block tryStartBlock = Reader.GetOrCreateBlock(this.blockMap, tryOffset); + Block blockAfterTryEnd = Reader.GetOrCreateBlock(this.blockMap, tryOffset + tryLength); + Block handlerStartBlock = Reader.GetOrCreateBlock(this.blockMap, handlerOffset); + Block blockAfterHandlerEnd = Reader.GetOrCreateBlock(this.blockMap, handlerOffset + handlerLength); + List<TryNode> tryList = null; + if (!this.tryMap.TryGetValue(tryStartBlock, out tryList)) { + this.tryMap[tryStartBlock] = tryList = new List<TryNode>(); + } + TryNode currentTry = null; + int tryEnd = tryOffset + tryLength; + foreach (TryNode t in tryList) { + if (t.tryEnd == tryEnd) { + currentTry = t; + break; + } + } + if (currentTry == null) { + currentTry = new TryNode(); + currentTry.tryEnd = tryEnd; + tryList.Add(currentTry); + } + int handlerEnd = handlerOffset + handlerLength; + if (currentTry.handlersEnd < handlerEnd) + currentTry.handlersEnd = handlerEnd; + + Debug.Assert((int)flags != 3); + Debug.Assert((int)flags < 5); + + switch (flags) { + case 0x00: + // for a catch handler, tokenOrOffset represents + // the metadata token of the handler type. handlerOffset + // is the literal offset for the catch block + int pos = this.reader.tables.GetCurrentPosition(); + TypeNode filterType = (TypeNode)this.reader.GetMemberFromToken(tokenOrOffset); + this.reader.tables.SetCurrentPosition(pos); + string variableName = "$exception" + this.handlerMap.Count.ToString(CultureInfo.InvariantCulture); + StackVariable exception = new StackVariable(filterType, variableName); + CatchNode c = new CatchNode(handlerStartBlock, exception, filterType); + c.handlerEnd = handlerEnd; + currentTry.Catchers.Add(c); + this.handlerMap[handlerOffset] = exception; + break; + case 0x01: + // for a filter, tokenOrOffset represents the IL offset + // of the filter block. handlerOffset represents + // the IL offset of the associated catch handler + Block filterExpression = Reader.GetOrCreateBlock(blockMap, tokenOrOffset); + variableName = "$exception" + this.handlerMap.Count.ToString(CultureInfo.InvariantCulture); + exception = new StackVariable(CoreSystemTypes.Object, variableName); + Filter filter = new Filter(filterExpression, exception); + filter.handlerEnd = handlerOffset; + c = new CatchNode(handlerStartBlock, exception, null, filter); + c.handlerEnd = handlerEnd; + currentTry.Catchers.Add(c); + // note that handlerOffset would not be correct here! + this.handlerMap[tokenOrOffset] = exception; + break; + case 0x02: + FinallyNode f = new FinallyNode(handlerStartBlock); + f.handlerEnd = handlerEnd; + currentTry.Finally = f; + break; + case 0x04: + FaultHandler fh = new FaultHandler(handlerStartBlock); + fh.handlerEnd = handlerEnd; + currentTry.FaultHandler = fh; + break; + } + } + } + private void ProcessBlock(Block currentBlock, ref int counter, int blockEnd, Node blockNode) { + while (true) { + int lastCounter = counter; + Block block = GetNextBlock(ref counter); + if (block == null || block.ILOffset >= blockEnd) { + counter = lastCounter; + if (blockNode != null) + blockNode.SourceContext = currentBlock.Statements[0].SourceContext; + return; + } + if (this.tryMap.ContainsKey(block)) { + ProcessTryBlock(currentBlock, block, ref counter); + } + else { + if (currentBlock.Statements.Count == 0) + currentBlock.SourceContext = block.SourceContext; + currentBlock.Statements.Add(block); + } + } + } + private void ProcessTryBlock(Block outerBlock, Block currentBlock, ref int counter) { + List<TryNode> tryList = this.tryMap[currentBlock]; + TryNode outerTry = tryList[tryList.Count - 1]; + outerBlock.Statements.Add(outerTry); + tryList.Remove(outerTry); + if (tryList.Count > 0) { + outerTry.Block = new Block(); + outerTry.Block.Statements = new StatementList(); + ProcessTryBlock(outerTry.Block, currentBlock, ref counter); + } + else { + outerTry.Block = currentBlock; + } + this.tryMap.Remove(currentBlock); + ProcessBlock(outerTry.Block, ref counter, outerTry.tryEnd, outerTry); + while (true) { + int lastCounter = counter; + Block block = GetNextBlock(ref counter); + if (counter >= outerTry.handlersEnd) { + counter = lastCounter; + return; + } + int handlerEnd; + Node handlerNode; + GetHandlerEnd(outerTry, block, out handlerEnd, out handlerNode); + ProcessBlock(block, ref counter, handlerEnd, handlerNode); + } + } + private Block GetNextBlock(ref int counter) { + while (true) { + Block result = this.blockMap[counter + 1] as Block; + ++counter; + if (result != null || counter >= this.size) + return result; + } + } + private void GetHandlerEnd(TryNode t, Block block, out int handlerEnd, out Node handlerNode) { + handlerEnd = Int32.MaxValue; + handlerNode = null; + int startPos = block.ILOffset; + if (t.Finally != null + && t.Finally.handlerEnd > startPos + && t.Finally.handlerEnd < handlerEnd) { + handlerEnd = t.Finally.handlerEnd; + handlerNode = t.Finally; + } + foreach (CatchNode c in t.Catchers) { + if (c.handlerEnd > startPos && c.handlerEnd < handlerEnd) { + handlerEnd = c.handlerEnd; + handlerNode = c; + } + if (c.Filter != null && c.Filter.handlerEnd > startPos && c.Filter.handlerEnd < handlerEnd) { + handlerEnd = c.Filter.handlerEnd; + handlerNode = c.Filter; + } + } + if (t.FaultHandler != null + && t.FaultHandler.handlerEnd > startPos + && t.FaultHandler.handlerEnd < handlerEnd) { + handlerEnd = t.FaultHandler.handlerEnd; + handlerNode = t.FaultHandler; + } + } +#endif + } + internal class InstructionParser : ILParser + { + private readonly TrivialHashtable/*!*/ ehMap; + internal InstructionParser(Reader/*!*/ reader, Method/*!*/ method, int methodIndex, int RVA) + : base(reader, method, methodIndex, RVA) + { + this.ehMap = new TrivialHashtable(); + } + override protected void ParseExceptionHandlerEntry(bool smallSection) + { + TrivialHashtable tryMap = new TrivialHashtable(); + int dataSize = this.reader.tables.GetByte(); + int n = (int)(ushort)this.reader.tables.GetInt16(); + if (smallSection) + n = dataSize / 12; + else + n = (dataSize + (n << 8)) / 24; + for (int i = 0; i < n; i++) + { + Instruction matchingInstruction; + int flags, tryOffset, tryLength, handlerOffset, handlerLength, tokenOrOffset; + if (smallSection) + { + flags = this.reader.tables.GetInt16(); + tryOffset = this.reader.tables.GetUInt16(); + tryLength = this.reader.tables.GetByte(); + handlerOffset = this.reader.tables.GetUInt16(); + handlerLength = this.reader.tables.GetByte(); + } + else + { + flags = this.reader.tables.GetInt32(); + tryOffset = this.reader.tables.GetInt32(); + tryLength = this.reader.tables.GetInt32(); + handlerOffset = this.reader.tables.GetInt32(); + handlerLength = this.reader.tables.GetInt32(); + } + tokenOrOffset = this.reader.tables.GetInt32(); + if (tryMap[tryOffset + tryLength] == null) + { + matchingInstruction = this.AddInstruction(OpCode._Try, tryOffset); + this.AddInstruction(OpCode._EndTry, tryOffset + tryLength, matchingInstruction); + tryMap[tryOffset + tryLength] = String.Empty; + } + switch (flags) + { + case 0x00: + int pos = this.reader.tables.GetCurrentPosition(); + TypeNode catchType = (TypeNode)this.reader.GetMemberFromToken(tokenOrOffset); + this.reader.tables.SetCurrentPosition(pos); + matchingInstruction = this.AddInstruction(OpCode._Catch, handlerOffset, catchType); + this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction); + break; + case 0x01: + matchingInstruction = this.AddInstruction(OpCode._Filter, tokenOrOffset); + this.AddInstruction(OpCode._EndFilter, handlerOffset, matchingInstruction); + matchingInstruction = this.AddInstruction(OpCode._Catch, handlerOffset); + this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction); + break; + case 0x02: + matchingInstruction = this.AddInstruction(OpCode._Finally, handlerOffset); + this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction); + break; + case 0x04: + matchingInstruction = this.AddInstruction(OpCode._Fault, handlerOffset); + this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction); + break; + default: throw new InvalidMetadataException(ExceptionStrings.BadExceptionHandlerType); + } + } + } + private Instruction AddInstruction(OpCode opCode, int offset) + { + return this.AddInstruction(opCode, offset, null); + } + private Instruction AddInstruction(OpCode opCode, int offset, object value) + { + Instruction instruction = new Instruction(opCode, offset, value); + InstructionList instructions = (InstructionList)this.ehMap[offset + 1]; + if (instructions == null) this.ehMap[offset + 1] = instructions = new InstructionList(2); + instructions.Add(instruction); +#if !ROTOR + if (this.method.contextForOffset != null) + { + object sctx = this.method.contextForOffset[offset + 1]; + if (sctx != null) instruction.SourceContext = (SourceContext)sctx; + } +#endif + return instruction; + } + private Int32List ParseSwitchInstruction() + { + int numTargets = this.GetInt32(); + Int32List result = new Int32List(numTargets); + int offset = this.counter + numTargets * 4; + for (int i = 0; i < numTargets; i++) + { + int targetAddress = this.GetInt32() + offset; + result.Add(targetAddress); + } + return result; + } + internal InstructionList ParseInstructions() + { + this.ParseHeader(); + if (this.size == 0) return new InstructionList(0); + InstructionList result = new InstructionList(); + result.Add(new Instruction(OpCode._Locals, 0, this.locals)); + while (this.counter <= size) + { + InstructionList instructions = (InstructionList)this.ehMap[this.counter + 1]; + if (instructions != null) + { + for (int i = 0; i < instructions.Count; i++) + result.Add(instructions[i]); + } + if (this.counter < size) + result.Add(this.ParseInstruction()); + else + break; + } + return result; + } + private SourceContext sourceContext = new SourceContext(); + internal Instruction ParseInstruction() + { + if (this.counter >= this.size) + return null; + int offset = this.counter; +#if !ROTOR + if (this.method.contextForOffset != null) + { + object sctx = this.method.contextForOffset[offset + 1]; + if (sctx != null) this.sourceContext = (SourceContext)sctx; + } +#endif + object value = null; + OpCode opCode = this.GetOpCode(); + switch (opCode) + { + case OpCode.Nop: + case OpCode.Break: + break; + case OpCode.Ldarg_0: value = this.Parameters(0); break; + case OpCode.Ldarg_1: value = this.Parameters(1); break; + case OpCode.Ldarg_2: value = this.Parameters(2); break; + case OpCode.Ldarg_3: value = this.Parameters(3); break; + case OpCode.Ldloc_0: value = this.locals[0]; break; + case OpCode.Ldloc_1: value = this.locals[1]; break; + case OpCode.Ldloc_2: value = this.locals[2]; break; + case OpCode.Ldloc_3: value = this.locals[3]; break; + case OpCode.Stloc_0: value = this.locals[0]; break; + case OpCode.Stloc_1: value = this.locals[1]; break; + case OpCode.Stloc_2: value = this.locals[2]; break; + case OpCode.Stloc_3: value = this.locals[3]; break; + case OpCode.Ldarg_S: + case OpCode.Ldarga_S: + case OpCode.Starg_S: + value = this.Parameters(this.GetByte()); break; + case OpCode.Ldloc_S: + case OpCode.Ldloca_S: + case OpCode.Stloc_S: + value = this.locals[this.GetByte()]; break; + case OpCode.Ldnull: + break; + case OpCode.Ldc_I4_M1: value = (Int32)(-1); break; + case OpCode.Ldc_I4_0: value = (Int32)0; break; + case OpCode.Ldc_I4_1: value = (Int32)1; break; + case OpCode.Ldc_I4_2: value = (Int32)2; break; + case OpCode.Ldc_I4_3: value = (Int32)3; break; + case OpCode.Ldc_I4_4: value = (Int32)4; break; + case OpCode.Ldc_I4_5: value = (Int32)5; break; + case OpCode.Ldc_I4_6: value = (Int32)6; break; + case OpCode.Ldc_I4_7: value = (Int32)7; break; + case OpCode.Ldc_I4_8: value = (Int32)8; break; + case OpCode.Ldc_I4_S: value = (Int32)this.GetSByte(); break; + case OpCode.Ldc_I4: value = this.GetInt32(); break; + case OpCode.Ldc_I8: value = this.GetInt64(); break; + case OpCode.Ldc_R4: value = this.GetSingle(); break; + case OpCode.Ldc_R8: value = this.GetDouble(); break; + case OpCode.Dup: + case OpCode.Pop: + break; + case OpCode.Jmp: + case OpCode.Call: + value = (Method)this.GetMemberFromToken(); break; + case OpCode.Calli: + value = (FunctionPointer)this.reader.GetCalliSignature(this.GetInt32()); break; + case OpCode.Ret: break; + case OpCode.Br_S: + case OpCode.Brfalse_S: + case OpCode.Brtrue_S: + case OpCode.Beq_S: + case OpCode.Bge_S: + case OpCode.Bgt_S: + case OpCode.Ble_S: + case OpCode.Blt_S: + case OpCode.Bne_Un_S: + case OpCode.Bge_Un_S: + case OpCode.Bgt_Un_S: + case OpCode.Ble_Un_S: + case OpCode.Blt_Un_S: + value = this.counter + 1 + this.GetSByte(); break; + case OpCode.Br: + case OpCode.Brfalse: + case OpCode.Brtrue: + case OpCode.Beq: + case OpCode.Bge: + case OpCode.Bgt: + case OpCode.Ble: + case OpCode.Blt: + case OpCode.Bne_Un: + case OpCode.Bge_Un: + case OpCode.Bgt_Un: + case OpCode.Ble_Un: + case OpCode.Blt_Un: + value = this.counter + 4 + this.GetInt32(); break; + case OpCode.Switch: value = this.ParseSwitchInstruction(); break; + case OpCode.Ldind_I1: + case OpCode.Ldind_U1: + case OpCode.Ldind_I2: + case OpCode.Ldind_U2: + case OpCode.Ldind_I4: + case OpCode.Ldind_U4: + case OpCode.Ldind_I8: + case OpCode.Ldind_I: + case OpCode.Ldind_R4: + case OpCode.Ldind_R8: + case OpCode.Ldind_Ref: + case OpCode.Stind_Ref: + case OpCode.Stind_I1: + case OpCode.Stind_I2: + case OpCode.Stind_I4: + case OpCode.Stind_I8: + case OpCode.Stind_R4: + case OpCode.Stind_R8: + case OpCode.Add: + case OpCode.Sub: + case OpCode.Mul: + case OpCode.Div: + case OpCode.Div_Un: + case OpCode.Rem: + case OpCode.Rem_Un: + case OpCode.And: + case OpCode.Or: + case OpCode.Xor: + case OpCode.Shl: + case OpCode.Shr: + case OpCode.Shr_Un: + case OpCode.Neg: + case OpCode.Not: + case OpCode.Conv_I1: + case OpCode.Conv_I2: + case OpCode.Conv_I4: + case OpCode.Conv_I8: + case OpCode.Conv_R4: + case OpCode.Conv_R8: + case OpCode.Conv_U4: + case OpCode.Conv_U8: + break; + case OpCode.Callvirt: value = (Method)this.GetMemberFromToken(); break; + case OpCode.Cpobj: + case OpCode.Ldobj: + value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Ldstr: value = this.GetStringFromToken(); break; + case OpCode.Newobj: value = (Method)this.GetMemberFromToken(); break; + case OpCode.Castclass: + case OpCode.Isinst: + value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Conv_R_Un: break; + case OpCode.Unbox: value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Throw: break; + case OpCode.Ldfld: + case OpCode.Ldflda: + case OpCode.Stfld: + case OpCode.Ldsfld: + case OpCode.Ldsflda: + case OpCode.Stsfld: + case OpCode.Stobj: + value = this.GetMemberFromToken(); break; + case OpCode.Conv_Ovf_I1_Un: + case OpCode.Conv_Ovf_I2_Un: + case OpCode.Conv_Ovf_I4_Un: + case OpCode.Conv_Ovf_I8_Un: + case OpCode.Conv_Ovf_U1_Un: + case OpCode.Conv_Ovf_U2_Un: + case OpCode.Conv_Ovf_U4_Un: + case OpCode.Conv_Ovf_U8_Un: + case OpCode.Conv_Ovf_I_Un: + case OpCode.Conv_Ovf_U_Un: + break; + case OpCode.Box: + case OpCode.Newarr: value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Ldlen: break; + case OpCode.Ldelema: value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Ldelem_I1: + case OpCode.Ldelem_U1: + case OpCode.Ldelem_I2: + case OpCode.Ldelem_U2: + case OpCode.Ldelem_I4: + case OpCode.Ldelem_U4: + case OpCode.Ldelem_I8: + case OpCode.Ldelem_I: + case OpCode.Ldelem_R4: + case OpCode.Ldelem_R8: + case OpCode.Ldelem_Ref: + case OpCode.Stelem_I: + case OpCode.Stelem_I1: + case OpCode.Stelem_I2: + case OpCode.Stelem_I4: + case OpCode.Stelem_I8: + case OpCode.Stelem_R4: + case OpCode.Stelem_R8: + case OpCode.Stelem_Ref: + break; + case OpCode.Ldelem: + value = (TypeNode)this.GetMemberFromToken(); + break; + case OpCode.Stelem: value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Unbox_Any: value = this.GetMemberFromToken(); break; + case OpCode.Conv_Ovf_I1: + case OpCode.Conv_Ovf_U1: + case OpCode.Conv_Ovf_I2: + case OpCode.Conv_Ovf_U2: + case OpCode.Conv_Ovf_I4: + case OpCode.Conv_Ovf_U4: + case OpCode.Conv_Ovf_I8: + case OpCode.Conv_Ovf_U8: + break; + case OpCode.Refanyval: value = this.GetMemberFromToken(); break; + case OpCode.Ckfinite: break; + case OpCode.Mkrefany: value = this.GetMemberFromToken(); break; + case OpCode.Ldtoken: value = this.GetMemberFromToken(); break; + case OpCode.Conv_U2: + case OpCode.Conv_U1: + case OpCode.Conv_I: + case OpCode.Conv_Ovf_I: + case OpCode.Conv_Ovf_U: + case OpCode.Add_Ovf: + case OpCode.Add_Ovf_Un: + case OpCode.Mul_Ovf: + case OpCode.Mul_Ovf_Un: + case OpCode.Sub_Ovf: + case OpCode.Sub_Ovf_Un: + case OpCode.Endfinally: + break; + case OpCode.Leave: value = this.counter + 4 + this.GetInt32(); break; + case OpCode.Leave_S: value = this.counter + 1 + this.GetSByte(); break; + case OpCode.Stind_I: + case OpCode.Conv_U: + case OpCode.Prefix7: + case OpCode.Prefix6: + case OpCode.Prefix5: + case OpCode.Prefix4: + case OpCode.Prefix3: + case OpCode.Prefix2: + case OpCode.Prefix1: + case OpCode.Arglist: + case OpCode.Ceq: + case OpCode.Cgt: + case OpCode.Cgt_Un: + case OpCode.Clt: + case OpCode.Clt_Un: + break; + case OpCode.Ldftn: + case OpCode.Ldvirtftn: + value = this.GetMemberFromToken(); break; + case OpCode.Ldarg: + case OpCode.Ldarga: + case OpCode.Starg: + value = this.Parameters(this.GetInt16()); break; + case OpCode.Ldloc: + case OpCode.Ldloca: + case OpCode.Stloc: + value = this.locals[this.GetInt16()]; break; + case OpCode.Localloc: + case OpCode.Endfilter: + break; + case OpCode.Unaligned_: value = this.GetByte(); break; + case OpCode.Volatile_: + case OpCode.Tail_: + break; + case OpCode.Initobj: value = (TypeNode)this.GetMemberFromToken(); break; + case OpCode.Constrained_: value = this.GetMemberFromToken() as TypeNode; break; + case OpCode.Cpblk: + case OpCode.Initblk: + break; + case OpCode.Rethrow: + break; + case OpCode.Sizeof: value = this.GetMemberFromToken(); break; + case OpCode.Refanytype: + case OpCode.Readonly_: + break; + default: throw new InvalidMetadataException(String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.UnknownOpCodeEncountered, opCode.ToString("x"))); + } + Instruction instruction = new Instruction(opCode, offset, value); + instruction.SourceContext = this.sourceContext; + return instruction; + } + } + internal class ExpressionStack + { + internal Expression[]/*!*/ elements = new Expression[64]; + internal int top = -1; + + internal ExpressionStack() + { + //^ base(); + } + + private void Grow() + { + int n = this.elements.Length; + Expression[] newElements = new Expression[n + 64]; + for (int i = 0; i < n; i++) newElements[i] = this.elements[i]; + this.elements = newElements; + } + internal Expression/*!*/ Pop() + { + if (this.top < 0) return new Expression(NodeType.Pop); + Expression e = this.elements[this.top--]; + //^ assume e != null; + return e; + } + internal void Push(Expression/*!*/ e) + { + if (++this.top >= this.elements.Length) this.Grow(); + this.elements[this.top] = e; + } + } + /// <summary> + /// A thin wrapper for a synchronized System.Collections.Hashtable that inserts and strips WeakReference wrappers for the values stored in the table. + /// </summary> + internal class SynchronizedWeakDictionary : IDictionary + { + private Hashtable/*!*/ Hashtable = System.Collections.Hashtable.Synchronized(new Hashtable()); + + internal SynchronizedWeakDictionary() + { + //^ base(); + } + + public void Add(object/*!*/ key, object value) + { + this.Hashtable.Add(key, new WeakReference(value)); + } + public void Clear() + { + this.Hashtable.Clear(); + } + public bool Contains(object/*!*/ key) + { + return this.Hashtable.Contains(key); + } + public IDictionaryEnumerator/*!*/ GetEnumerator() + { + return this.Hashtable.GetEnumerator(); + } + public bool IsFixedSize + { + get { return false; } + } + public bool IsReadOnly + { + get { return false; } + } + public ICollection/*!*/ Keys + { + get { return this.Hashtable.Keys; } + } + public void Remove(object/*!*/ key) + { + this.Hashtable.Remove(key); + } + public ICollection/*!*/ Values + { + get { return new WeakValuesCollection(this.Hashtable.Values); } + } + public object this[object/*!*/ key] + { + get + { + WeakReference wref = (WeakReference)this.Hashtable[key]; + if (wref == null) return null; + return wref.Target; + } + set + { + this.Hashtable[key] = new WeakReference(value); + } + } + public void CopyTo(Array/*!*/ array, int index) + { + IEnumerator enumerator = this.GetEnumerator(); + for (int i = 0; enumerator.MoveNext(); i++) + array.SetValue(enumerator.Current, index + i); + } + public int Count + { + get { return this.Hashtable.Count; } + } + public bool IsSynchronized + { + get { return false; } + } + public object/*!*/ SyncRoot + { + get { return this.Hashtable.SyncRoot; } + } + IEnumerator/*!*/ IEnumerable.GetEnumerator() + { + return new WeakValuesEnumerator(this.Hashtable.GetEnumerator()); + } + } + internal class WeakValuesCollection : ICollection + { + private ICollection/*!*/ collection; + + internal WeakValuesCollection(ICollection/*!*/ collection) + { + this.collection = collection; + //^ base(); + } + + public void CopyTo(Array/*!*/ array, int index) + { + IEnumerator enumerator = this.GetEnumerator(); + for (int i = 0; enumerator.MoveNext(); i++) + array.SetValue(enumerator.Current, index + i); + } + public int Count + { + get { return this.collection.Count; } + } + public bool IsSynchronized + { + get { return this.collection.IsSynchronized; } + } + public object/*!*/ SyncRoot + { + get { return this.collection.SyncRoot; } + } + public IEnumerator/*!*/ GetEnumerator() + { + return new WeakValuesEnumerator(this.collection.GetEnumerator()); + } + } + internal class WeakValuesEnumerator : IEnumerator + { + private IEnumerator/*!*/ enumerator; + + internal WeakValuesEnumerator(IEnumerator/*!*/ enumerator) + { + this.enumerator = enumerator; + //^ base(); + } + + public object Current + { + get + { + object curr = this.enumerator.Current; + if (curr is DictionaryEntry) + { + DictionaryEntry dicEntry = (DictionaryEntry)curr; + curr = dicEntry.Value; + } + WeakReference wref = curr as WeakReference; + if (wref != null) return wref.Target; + return null; + } + } + public bool MoveNext() + { + return this.enumerator.MoveNext(); + } + public void Reset() + { + this.enumerator.Reset(); + } + } +#if !ROTOR && NoWriter + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44")] + internal interface IMetaDataImport{} + internal class EmptyImporter : IMetaDataImport{} +#endif +#if FxCop + class StackVariable : Local { + internal StackVariable(TypeNode type, string name) + : base(type) { + this.NodeType = NodeType.StackVariable; + this.Name = Identifier.For(name); + } + internal StackVariable(TypeNode type, int index) + : base(type) { + this.NodeType = NodeType.StackVariable; + this.Name = Identifier.For("stack$" + index.ToString(CultureInfo.InvariantCulture)); + } + } +#endif +} |