PageRenderTime 100ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 2ms

/SHFB/Source/MRefBuilder/CCI/Reader.cs

#
C# | 5822 lines | 5398 code | 311 blank | 113 comment | 1647 complexity | 4e5dc2e8accf5056413d2140985e6bc7 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // Copyright Š Microsoft Corporation.
  2. // This source file is subject to the Microsoft Permissive License.
  3. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
  4. // All other rights reserved.
  5. // Change history:
  6. // 11/21/2013 - EFW - Cleared out the conditional statements and updated based on changes to ListTemplate.cs.
  7. // 12/15/2013 - EFW - Fixed a bug found when parsing the .NET 4.5.1 Framework assemblies
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Globalization;
  12. using System.IO;
  13. using System.Linq;
  14. using Marshal = System.Runtime.InteropServices.Marshal;
  15. using System.Runtime.InteropServices;
  16. namespace System.Compiler.Metadata
  17. {
  18. enum CorOpenFlags : uint
  19. {
  20. ofRead = 0x00000000, // Open scope for read
  21. ofWrite = 0x00000001, // Open scope for write.
  22. ofCopyMemory = 0x00000002, // Open scope with memory. Ask metadata to maintain its own copy of memory.
  23. ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image
  24. ofNoTypeLib = 0x00000080, // Don't OpenScope on a typelib.
  25. }
  26. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("809c652e-7396-11d2-9771-00A0C9B4D50C")]
  27. interface IMetaDataDispenser
  28. {
  29. void DefineScope(ref Guid clsid, uint createFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object retval);
  30. [PreserveSig]
  31. int OpenScope(string scope, uint openFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object import);
  32. void OpenScopeOnMemory(IntPtr data, uint dataSize, uint openFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object retval);
  33. }
  34. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("AA544D42-28CB-11d3-BD22-0000F80849BD")]
  35. interface ISymUnmanagedBinder
  36. {
  37. [PreserveSig]
  38. int GetReaderForFile([MarshalAs(UnmanagedType.IUnknown)] object importer, string filename, string searchPath, out ISymUnmanagedReader reader);
  39. ISymUnmanagedReader GetReaderForStream([MarshalAs(UnmanagedType.IUnknown)] object importer, [MarshalAs(UnmanagedType.IUnknown)] object stream);
  40. }
  41. [ComImport, Guid("ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(false)]
  42. interface ISymUnmanagedBinder2 : ISymUnmanagedBinder
  43. {
  44. void GetReaderForFile(IntPtr importer, [MarshalAs(UnmanagedType.LPWStr)] String filename, [MarshalAs(UnmanagedType.LPWStr)] String SearchPath, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader retVal);
  45. void GetReaderFromStream(IntPtr importer, IntPtr stream, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader retVal);
  46. [PreserveSig]
  47. 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);
  48. // void GetReaderForFile3(IntPtr importer, [MarshalAs(UnmanagedType.LPWStr)] String fileName, [MarshalAs(UnmanagedType.LPWStr)] String searchPath, int searchPolicy, IntPtr callback, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader pRetVal);
  49. }
  50. [ComImport, Guid("AA544D41-28CB-11d3-BD22-0000F80849BD")]
  51. class CorSymBinder
  52. {
  53. }
  54. [ComImport, Guid("0A29FF9E-7F9C-4437-8B11-F424491E3931")]
  55. class CorSymBinder2
  56. {
  57. }
  58. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5")]
  59. interface ISymUnmanagedReader
  60. {
  61. ISymUnmanagedDocument GetDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType);
  62. void GetDocuments(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] docs);
  63. uint GetUserEntryPoint();
  64. [PreserveSig]
  65. int GetMethod(uint token, ref ISymUnmanagedMethod method);
  66. ISymUnmanagedMethod GetMethodByVersion(uint token, int version);
  67. void GetVariables(uint parent, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ISymUnmanagedVariable[] vars);
  68. void GetGlobalVariables(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] vars);
  69. ISymUnmanagedMethod GetMethodFromDocumentPosition(ISymUnmanagedDocument document, uint line, uint column);
  70. void GetSymAttribute(uint parent, string name, ulong size, ref uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer);
  71. void GetNamespaces(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] namespaces);
  72. void Initialize([MarshalAs(UnmanagedType.IUnknown)] object importer, string filename, string searchPath, [MarshalAs(UnmanagedType.IUnknown)] object stream);
  73. void UpdateSymbolStore(string filename, [MarshalAs(UnmanagedType.IUnknown)] object stream);
  74. void ReplaceSymbolStore(string filename, [MarshalAs(UnmanagedType.IUnknown)] object stream);
  75. void GetSymbolStoreFileName(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] name);
  76. void GetMethodsFromDocumentPosition(ISymUnmanagedDocument document, uint line, uint column, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] ISymUnmanagedMethod[] retval);
  77. void GetDocumentVersion(ISymUnmanagedDocument doc, out int version, out bool isLatest);
  78. void GetMethodVersion(ISymUnmanagedMethod method, out int version);
  79. }
  80. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B62B923C-B500-3158-A543-24F307A8B7E1")]
  81. interface ISymUnmanagedMethod
  82. {
  83. uint GetToken();
  84. uint GetSequencePointCount();
  85. ISymUnmanagedScope GetRootScope();
  86. ISymUnmanagedScope GetScopeFromOffset(uint offset);
  87. uint Getoffset(ISymUnmanagedDocument document, uint line, uint column);
  88. void GetRanges(ISymUnmanagedDocument document, uint line, uint column, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] ranges);
  89. void GetParameters(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] parms);
  90. IntPtr GetNamespace();
  91. bool GetSourceStartEnd([MarshalAs(UnmanagedType.LPArray, SizeConst = 2)] ISymUnmanagedDocument[] docs, [MarshalAs(UnmanagedType.LPArray)] uint[] lines, [MarshalAs(UnmanagedType.LPArray)] uint[] columns);
  92. void GetSequencePoints(uint size, out uint length,
  93. [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] offsets,
  94. [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, SizeParamIndex = 0)] IntPtr[] documents,
  95. [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] lines,
  96. [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] columns,
  97. [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] endLines,
  98. [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] endColumns);
  99. }
  100. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08")]
  101. interface ISymUnmanagedDocument
  102. {
  103. void GetURL(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] url);
  104. void GetDocumentType(out Guid retval);
  105. void GetLanguage(out Guid retval);
  106. void GetLanguageVendor(out Guid retval);
  107. void GetCheckSumAlgorithmId(out Guid retval);
  108. void GetCheckSum(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] data);
  109. uint FindClosestLine(uint line);
  110. bool HasEmbeddedSource();
  111. uint GetSourceLength();
  112. void GetSourceRange(uint startLine, uint startColumn, uint endLine, uint endColumn, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] source);
  113. }
  114. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB")]
  115. interface ISymUnmanagedVariable
  116. {
  117. void GetName(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] name);
  118. uint GetAttributes();
  119. void GetSignature(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] name);
  120. uint GetAddressKind();
  121. uint GetAddressField1();
  122. uint GetAddressField2();
  123. uint GetAddressField3();
  124. uint GetStartOffset();
  125. uint GetEndOffset();
  126. }
  127. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("68005D0F-B8E0-3B01-84D5-A11A94154942")]
  128. interface ISymUnmanagedScope
  129. {
  130. ISymUnmanagedMethod GetMethod();
  131. ISymUnmanagedScope GetParent();
  132. void GetChildren(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] children);
  133. uint GetStartOffset();
  134. uint GetEndOffset();
  135. uint GetLocalCount();
  136. void GetLocals(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] locals);
  137. void GetNamespaces(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] namespaces);
  138. }
  139. internal sealed class UnmanagedBuffer : IDisposable
  140. {
  141. internal IntPtr Pointer;
  142. internal UnmanagedBuffer(int length)
  143. {
  144. this.Pointer = Marshal.AllocHGlobal(length);
  145. }
  146. public void Dispose()
  147. {
  148. if (this.Pointer != IntPtr.Zero)
  149. Marshal.FreeHGlobal(this.Pointer);
  150. this.Pointer = IntPtr.Zero;
  151. GC.SuppressFinalize(this);
  152. }
  153. ~UnmanagedBuffer()
  154. {
  155. this.Dispose();
  156. }
  157. }
  158. internal unsafe class Reader : IDisposable
  159. {
  160. private string directory;
  161. private string fileName;
  162. private bool doNotLockFile;
  163. private Module/*!*/ module = new Module();
  164. internal TypeNode currentType;
  165. private long sortedTablesMask;
  166. internal MetadataReader/*!*/ tables;
  167. private UnmanagedBuffer unmanagedBuffer;
  168. private int bufferLength;
  169. private IDictionary/*!*/ localAssemblyCache; //use for simple names
  170. internal readonly static IDictionary/*!*/ StaticAssemblyCache = new SynchronizedWeakDictionary(); //use for strong names
  171. private bool useStaticCache;
  172. //^ [Microsoft.Contracts.SpecInternal]
  173. private TrivialHashtable namespaceTable;
  174. internal NamespaceList namespaceList;
  175. internal ISymUnmanagedReader debugReader;
  176. internal bool getDebugSymbols;
  177. private bool getDebugSymbolsFailed;
  178. private TypeNodeList currentTypeParameters;
  179. private TypeNodeList currentMethodTypeParameters;
  180. internal bool preserveShortBranches;
  181. internal unsafe Reader(byte[]/*!*/ buffer, IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches)
  182. {
  183. Debug.Assert(buffer != null);
  184. if (localAssemblyCache == null) localAssemblyCache = new Hashtable();
  185. this.localAssemblyCache = localAssemblyCache;
  186. this.getDebugSymbols = getDebugInfo;
  187. this.doNotLockFile = false;
  188. this.useStaticCache = useStaticCache;
  189. this.preserveShortBranches = preserveShortBranches;
  190. int n = this.bufferLength = buffer.Length;
  191. this.unmanagedBuffer = new UnmanagedBuffer(n);
  192. //^ base();
  193. byte* pb = (byte*)this.unmanagedBuffer.Pointer;
  194. for (int i = 0; i < n; i++) *pb++ = buffer[i];
  195. }
  196. internal Reader(string/*!*/ fileName, IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches)
  197. {
  198. if (localAssemblyCache == null) localAssemblyCache = new Hashtable();
  199. this.localAssemblyCache = localAssemblyCache;
  200. fileName = System.IO.Path.GetFullPath(fileName);
  201. this.fileName = fileName;
  202. this.directory = System.IO.Path.GetDirectoryName(fileName);
  203. this.getDebugSymbols = getDebugInfo;
  204. this.doNotLockFile = doNotLockFile;
  205. this.useStaticCache = useStaticCache;
  206. this.preserveShortBranches = preserveShortBranches;
  207. //^ base();
  208. }
  209. internal Reader(IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches)
  210. {
  211. if (localAssemblyCache == null) localAssemblyCache = new Hashtable();
  212. this.localAssemblyCache = localAssemblyCache;
  213. this.directory = System.IO.Directory.GetCurrentDirectory();
  214. this.getDebugSymbols = getDebugInfo;
  215. this.doNotLockFile = doNotLockFile;
  216. this.useStaticCache = useStaticCache;
  217. this.preserveShortBranches = preserveShortBranches;
  218. //^ base();
  219. }
  220. public void Dispose()
  221. {
  222. if (this.unmanagedBuffer != null)
  223. this.unmanagedBuffer.Dispose();
  224. this.unmanagedBuffer = null;
  225. if (this.tables != null)
  226. this.tables.Dispose();
  227. //this.tables = null;
  228. if (this.debugReader != null)
  229. Marshal.ReleaseComObject(this.debugReader);
  230. this.debugReader = null;
  231. }
  232. private unsafe void SetupReader()
  233. {
  234. Debug.Assert(this.localAssemblyCache != null);
  235. if (this.doNotLockFile)
  236. {
  237. using (System.IO.FileStream inputStream = new System.IO.FileStream(this.fileName,
  238. System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
  239. {
  240. this.ReadFileIntoUnmanagedBuffer(inputStream);
  241. }
  242. }
  243. if (this.unmanagedBuffer == null)
  244. this.tables = new MetadataReader(this.fileName); //Uses a memory map that locks the file
  245. else
  246. this.tables = new MetadataReader((byte*)this.unmanagedBuffer.Pointer, this.bufferLength);
  247. //^ assume this.tables.tablesHeader != null;
  248. this.sortedTablesMask = this.tables.tablesHeader.maskSorted;
  249. }
  250. [DllImport("kernel32", SetLastError = true)]
  251. [return: MarshalAs(UnmanagedType.Bool)]
  252. static extern unsafe bool ReadFile(IntPtr FileHandle, byte* Buffer, int NumberOfBytesToRead, int* NumberOfBytesRead, IntPtr Overlapped);
  253. private unsafe void ReadFileIntoUnmanagedBuffer(System.IO.FileStream/*!*/ inputStream)
  254. {
  255. long size = inputStream.Seek(0, System.IO.SeekOrigin.End);
  256. if (size > int.MaxValue) throw new System.IO.FileLoadException();
  257. inputStream.Seek(0, System.IO.SeekOrigin.Begin);
  258. int n = (int)size;
  259. this.bufferLength = n;
  260. this.unmanagedBuffer = new UnmanagedBuffer(n);
  261. byte* pb = (byte*)this.unmanagedBuffer.Pointer;
  262. if(!Reader.ReadFile(inputStream.SafeFileHandle.DangerousGetHandle(), pb, n, &n, IntPtr.Zero))
  263. throw new System.IO.FileLoadException();
  264. }
  265. internal void SetupDebugReader(string filename, string pdbSearchPath)
  266. {
  267. if (filename == null) return;
  268. CorSymBinder binderObj1 = null;
  269. CorSymBinder2 binderObj2 = null;
  270. getDebugSymbolsFailed = false;
  271. object importer = null;
  272. try
  273. {
  274. int hresult = 0;
  275. try
  276. {
  277. binderObj2 = new CorSymBinder2();
  278. ISymUnmanagedBinder2 binder2 = (ISymUnmanagedBinder2)binderObj2;
  279. importer = new EmptyImporter();
  280. hresult = binder2.GetReaderForFile(importer, filename, pdbSearchPath, out this.debugReader);
  281. }
  282. catch (COMException e)
  283. {
  284. // could not instantiate ISymUnmanagedBinder2, fall back to ISymUnmanagedBinder
  285. if ((uint)e.ErrorCode == 0x80040111)
  286. {
  287. binderObj1 = new CorSymBinder();
  288. ISymUnmanagedBinder binder = (ISymUnmanagedBinder)binderObj1;
  289. hresult = binder.GetReaderForFile(importer, filename, null, out this.debugReader);
  290. }
  291. else
  292. {
  293. throw;
  294. }
  295. }
  296. switch ((uint)hresult)
  297. {
  298. case 0x0: break;
  299. case 0x806d0005: // EC_NOT_FOUND
  300. case 0x806d0014: // EC_INVALID_EXE_TIMESTAMP
  301. // Sometimes GetReaderForFile erroneously reports missing pdb files as being "out of date",
  302. // so we check if the file actually exists before reporting the error.
  303. // The mere absence of a pdb file is not an error. If not present, do not report.
  304. if (System.IO.File.Exists(System.IO.Path.ChangeExtension(filename, ".pdb")))
  305. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExceptionStrings.PdbAssociatedWithFileIsOutOfDate, filename));
  306. break;
  307. default:
  308. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
  309. ExceptionStrings.GetReaderForFileReturnedUnexpectedHResult, hresult.ToString("X")));
  310. }
  311. }
  312. catch (Exception e)
  313. {
  314. this.getDebugSymbols = false;
  315. this.getDebugSymbolsFailed = true;
  316. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  317. this.module.MetadataImportErrors.Add(e);
  318. }
  319. finally
  320. {
  321. if (binderObj1 != null) Marshal.ReleaseComObject(binderObj1);
  322. if (binderObj2 != null) Marshal.ReleaseComObject(binderObj2);
  323. }
  324. }
  325. private AssemblyNode ReadAssembly()
  326. {
  327. try
  328. {
  329. AssemblyNode assembly = new AssemblyNode(new Module.TypeNodeProvider(this.GetTypeFromName),
  330. new Module.TypeNodeListProvider(this.GetTypeList), new Module.CustomAttributeProvider(this.GetCustomAttributesFor),
  331. new Module.ResourceProvider(this.GetResources), this.directory);
  332. assembly.reader = this;
  333. this.ReadModuleProperties(assembly);
  334. this.ReadAssemblyProperties(assembly); //Hashvalue, Name, etc.
  335. this.module = assembly;
  336. this.ReadAssemblyReferences(assembly);
  337. this.ReadModuleReferences(assembly);
  338. AssemblyNode cachedAssembly = this.GetCachedAssembly(assembly);
  339. if (cachedAssembly != null) return cachedAssembly;
  340. if (this.getDebugSymbols) assembly.SetupDebugReader(null);
  341. assembly.AfterAssemblyLoadProcessing();
  342. return assembly;
  343. }
  344. catch (Exception e)
  345. {
  346. if (this.module == null) return null;
  347. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  348. this.module.MetadataImportErrors.Add(e);
  349. return this.module as AssemblyNode;
  350. }
  351. }
  352. private AssemblyNode GetCachedAssembly(AssemblyNode/*!*/ assembly)
  353. {
  354. //Always return the one true mscorlib. Things get too weird if more than one mscorlib is being read at the same time.
  355. //if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assembly.Name && CoreSystemTypes.SystemAssembly.reader != null) {
  356. // if (CoreSystemTypes.SystemAssembly.reader != this) {
  357. // if (this.getDebugSymbols && !CoreSystemTypes.SystemAssembly.reader.getDebugSymbols && !CoreSystemTypes.SystemAssembly.reader.getDebugSymbolsFailed)
  358. // CoreSystemTypes.SystemAssembly.SetupDebugReader(null);
  359. // this.Dispose();
  360. // }
  361. // return CoreSystemTypes.SystemAssembly;
  362. //}
  363. if (assembly.PublicKeyOrToken == null || assembly.PublicKeyOrToken.Length == 0)
  364. {
  365. AssemblyNode cachedAssembly = null;
  366. if (assembly.Location != null)
  367. cachedAssembly = this.localAssemblyCache[assembly.Location] as AssemblyNode;
  368. if (cachedAssembly == null && assembly.Name != null)
  369. {
  370. cachedAssembly = this.localAssemblyCache[assembly.Name] as AssemblyNode;
  371. if (cachedAssembly != null && assembly.Location != null)
  372. this.localAssemblyCache[assembly.Location] = cachedAssembly;
  373. }
  374. if (cachedAssembly != null)
  375. {
  376. if (cachedAssembly.reader != this && cachedAssembly.reader != null)
  377. {
  378. if (this.getDebugSymbols && !cachedAssembly.reader.getDebugSymbols && !cachedAssembly.reader.getDebugSymbolsFailed)
  379. cachedAssembly.SetupDebugReader(null);
  380. this.Dispose();
  381. }
  382. return cachedAssembly;
  383. }
  384. lock (Reader.StaticAssemblyCache)
  385. {
  386. if (assembly.Name != null)
  387. this.localAssemblyCache[assembly.Name] = assembly;
  388. if (this.fileName != null)
  389. this.localAssemblyCache[this.fileName] = assembly;
  390. }
  391. }
  392. else
  393. {
  394. string assemblyStrongName = assembly.StrongName;
  395. AssemblyNode cachedAssembly = null;
  396. if (this.useStaticCache)
  397. {
  398. //See if assembly is a platform assembly (and apply unification)
  399. AssemblyReference assemblyReference = new AssemblyReference(assembly);
  400. AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(assemblyReference.Name).UniqueIdKey];
  401. if (aRef != null && assemblyReference.Version != null && aRef.Version >= assemblyReference.Version && aRef.MatchesIgnoringVersion(assemblyReference))
  402. {
  403. AssemblyNode platformAssembly = aRef.assembly;
  404. if (platformAssembly == null)
  405. {
  406. Debug.Assert(aRef.Location != null);
  407. if (Path.GetFullPath(aRef.Location) == assembly.Location)
  408. {
  409. if (aRef.Version != assemblyReference.Version)
  410. {
  411. HandleError(assembly, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.BadTargetPlatformLocation, assembly.Name, TargetPlatform.PlatformAssembliesLocation, assembly.Version, aRef.Version));
  412. }
  413. lock (Reader.StaticAssemblyCache)
  414. {
  415. Reader.StaticAssemblyCache[assemblyStrongName] = assembly;
  416. if (aRef.Location != null)
  417. Reader.StaticAssemblyCache[aRef.Location] = assembly;
  418. }
  419. return null; //Prevents infinite recursion
  420. }
  421. platformAssembly = AssemblyNode.GetAssembly(aRef.Location, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  422. }
  423. if (platformAssembly != null)
  424. {
  425. lock (Reader.StaticAssemblyCache)
  426. {
  427. if (aRef.Location != null)
  428. Reader.StaticAssemblyCache[aRef.Location] = platformAssembly;
  429. Reader.StaticAssemblyCache[assemblyStrongName] = platformAssembly;
  430. }
  431. return aRef.assembly = platformAssembly;
  432. }
  433. }
  434. cachedAssembly = Reader.StaticAssemblyCache[assemblyStrongName] as AssemblyNode;
  435. if (cachedAssembly != null)
  436. {
  437. if (aRef == null && assembly.FileLastWriteTimeUtc > cachedAssembly.FileLastWriteTimeUtc &&
  438. assembly.Location != null && cachedAssembly.Location != null && assembly.Location == cachedAssembly.Location)
  439. {
  440. lock (Reader.StaticAssemblyCache)
  441. {
  442. Reader.StaticAssemblyCache[assemblyStrongName] = assembly;
  443. }
  444. return null;
  445. }
  446. if (cachedAssembly.reader != this && cachedAssembly.reader != null)
  447. {
  448. if (this.getDebugSymbols && !cachedAssembly.reader.getDebugSymbols && !cachedAssembly.reader.getDebugSymbolsFailed)
  449. cachedAssembly.SetupDebugReader(null);
  450. this.Dispose();
  451. }
  452. return cachedAssembly;
  453. }
  454. lock (Reader.StaticAssemblyCache)
  455. {
  456. Reader.StaticAssemblyCache[assemblyStrongName] = assembly;
  457. if (this.fileName != null)
  458. {
  459. Reader.StaticAssemblyCache[this.fileName] = assembly;
  460. }
  461. }
  462. }
  463. else
  464. {
  465. cachedAssembly = this.localAssemblyCache[assemblyStrongName] as AssemblyNode;
  466. if (cachedAssembly != null)
  467. {
  468. if (assembly.FileLastWriteTimeUtc > cachedAssembly.FileLastWriteTimeUtc &&
  469. assembly.Location != null && cachedAssembly.Location != null && assembly.Location == cachedAssembly.Location)
  470. {
  471. this.localAssemblyCache[assemblyStrongName] = assembly;
  472. return null;
  473. }
  474. if (cachedAssembly.reader != this && cachedAssembly.reader != null)
  475. {
  476. if (this.getDebugSymbols && cachedAssembly.reader.debugReader == null && !cachedAssembly.reader.getDebugSymbolsFailed)
  477. cachedAssembly.SetupDebugReader(null);
  478. this.Dispose();
  479. }
  480. return cachedAssembly;
  481. }
  482. this.localAssemblyCache[assemblyStrongName] = assembly;
  483. if (this.fileName != null) this.localAssemblyCache[this.fileName] = assembly;
  484. }
  485. }
  486. return null;
  487. }
  488. internal Module ReadModule()
  489. {
  490. try
  491. {
  492. if (this.fileName != null)
  493. {
  494. if (!System.IO.File.Exists(this.fileName)) return null;
  495. AssemblyNode cachedAssembly;
  496. if (this.useStaticCache)
  497. {
  498. cachedAssembly = Reader.StaticAssemblyCache[this.fileName] as AssemblyNode;
  499. if (cachedAssembly != null && cachedAssembly.FileLastWriteTimeUtc == System.IO.File.GetLastWriteTimeUtc(this.fileName))
  500. {
  501. this.Dispose();
  502. return cachedAssembly;
  503. }
  504. }
  505. cachedAssembly = this.localAssemblyCache[this.fileName] as AssemblyNode;
  506. if (cachedAssembly != null && cachedAssembly.FileLastWriteTimeUtc == System.IO.File.GetLastWriteTimeUtc(this.fileName))
  507. {
  508. this.Dispose();
  509. return cachedAssembly;
  510. }
  511. }
  512. this.SetupReader();
  513. if (this.tables.AssemblyTable.Length > 0) return this.ReadAssembly();
  514. Module module = this.module = new Module(new Module.TypeNodeProvider(this.GetTypeFromName),
  515. new Module.TypeNodeListProvider(this.GetTypeList), new Module.CustomAttributeProvider(this.GetCustomAttributesFor),
  516. new Module.ResourceProvider(this.GetResources));
  517. module.reader = this;
  518. this.ReadModuleProperties(module);
  519. this.module = module;
  520. this.ReadAssemblyReferences(module);
  521. this.ReadModuleReferences(module);
  522. if (this.getDebugSymbols) this.SetupDebugReader(this.fileName, null);
  523. return module;
  524. }
  525. catch (Exception e)
  526. {
  527. if (this.module == null) return null;
  528. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  529. this.module.MetadataImportErrors.Add(e);
  530. return module;
  531. }
  532. }
  533. private void ReadModuleProperties(Module/*!*/ module)
  534. {
  535. ModuleRow[] mods = this.tables.ModuleTable;
  536. if (mods.Length != 1) throw new InvalidMetadataException(ExceptionStrings.InvalidModuleTable);
  537. ModuleRow mrow = mods[0];
  538. module.reader = this;
  539. module.FileAlignment = this.tables.fileAlignment;
  540. module.HashValue = this.tables.HashValue;
  541. module.Kind = this.tables.moduleKind;
  542. module.Location = this.fileName;
  543. module.TargetRuntimeVersion = this.tables.targetRuntimeVersion;
  544. module.LinkerMajorVersion = this.tables.linkerMajorVersion;
  545. module.LinkerMinorVersion = this.tables.linkerMinorVersion;
  546. module.MetadataFormatMajorVersion = this.tables.metadataFormatMajorVersion;
  547. module.MetadataFormatMinorVersion = this.tables.metadataFormatMinorVersion;
  548. module.Name = this.tables.GetString(mrow.Name);
  549. module.Mvid = this.tables.GetGuid(mrow.Mvid);
  550. module.PEKind = this.tables.peKind;
  551. module.TrackDebugData = this.tables.TrackDebugData;
  552. }
  553. private void ReadAssemblyProperties(AssemblyNode/*!*/ assembly)
  554. {
  555. AssemblyRow assemblyRow = this.tables.AssemblyTable[0];
  556. assembly.HashAlgorithm = (AssemblyHashAlgorithm)assemblyRow.HashAlgId;
  557. assembly.Version = new System.Version(assemblyRow.MajorVersion, assemblyRow.MinorVersion, assemblyRow.BuildNumber, assemblyRow.RevisionNumber);
  558. assembly.Flags = (AssemblyFlags)assemblyRow.Flags;
  559. assembly.PublicKeyOrToken = this.tables.GetBlob(assemblyRow.PublicKey);
  560. assembly.ModuleName = assembly.Name;
  561. assembly.Name = this.tables.GetString(assemblyRow.Name);
  562. assembly.Culture = this.tables.GetString(assemblyRow.Culture);
  563. if (this.fileName != null)
  564. {
  565. assembly.FileLastWriteTimeUtc = System.IO.File.GetLastWriteTimeUtc(this.fileName);
  566. }
  567. assembly.ContainingAssembly = assembly;
  568. }
  569. private void ReadAssemblyReferences(Module/*!*/ module)
  570. {
  571. AssemblyRefRow[] assems = this.tables.AssemblyRefTable;
  572. int n = assems.Length;
  573. AssemblyReferenceList assemblies = module.AssemblyReferences = new AssemblyReferenceList();
  574. for(int i = 0; i < n; i++)
  575. {
  576. AssemblyRefRow arr = assems[i];
  577. AssemblyReference assemRef = new AssemblyReference();
  578. assemRef.Version = new System.Version(arr.MajorVersion, arr.MinorVersion, arr.BuildNumber, arr.RevisionNumber);
  579. assemRef.Flags = (AssemblyFlags)arr.Flags;
  580. assemRef.PublicKeyOrToken = this.tables.GetBlob(arr.PublicKeyOrToken);
  581. assemRef.Name = this.tables.GetString(arr.Name);
  582. //if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assemRef.Name &&
  583. // assemRef.Version > CoreSystemTypes.SystemAssembly.Version){
  584. // HandleError(module, ExceptionStrings.ModuleOrAssemblyDependsOnMoreRecentVersionOfCoreLibrary);
  585. //}
  586. assemRef.Culture = this.tables.GetString(arr.Culture);
  587. if(assemRef.Culture != null && assemRef.Culture.Length == 0)
  588. assemRef.Culture = null;
  589. assemRef.HashValue = this.tables.GetBlob(arr.HashValue);
  590. assemRef.Reader = this;
  591. assems[i].AssemblyReference = assemRef;
  592. assemblies.Add(assemRef);
  593. }
  594. }
  595. private void ReadModuleReferences(Module/*!*/ module)
  596. {
  597. FileRow[] files = this.tables.FileTable;
  598. ModuleRefRow[] modRefs = this.tables.ModuleRefTable;
  599. int n = modRefs.Length;
  600. ModuleReferenceList modules = module.ModuleReferences = new ModuleReferenceList();
  601. for(int i = 0; i < n; i++)
  602. {
  603. Module mod;
  604. int nameIndex = modRefs[i].Name;
  605. string name = this.tables.GetString(nameIndex);
  606. string dir = GetDirectoryName(this.module.Location);
  607. string location = Combine(dir, name);
  608. for (int j = 0, m = files == null ? 0 : files.Length; j < m; j++)
  609. {
  610. if(files[j].Name != nameIndex)
  611. continue;
  612. if ((files[j].Flags & (int)FileFlags.ContainsNoMetaData) == 0)
  613. mod = Module.GetModule(location, this.doNotLockFile, this.getDebugSymbols, false);
  614. else
  615. mod = null;
  616. if(mod == null)
  617. {
  618. mod = new Module();
  619. mod.Name = name;
  620. mod.Location = location;
  621. mod.Kind = ModuleKind.UnmanagedDynamicallyLinkedLibrary;
  622. }
  623. mod.HashValue = this.tables.GetBlob(files[j].HashValue);
  624. mod.ContainingAssembly = module.ContainingAssembly;
  625. modRefs[i].Module = mod;
  626. modules.Add(new ModuleReference(name, mod));
  627. goto nextModRef;
  628. }
  629. mod = new Module();
  630. mod.Name = name;
  631. mod.Kind = ModuleKind.UnmanagedDynamicallyLinkedLibrary;
  632. if (System.IO.File.Exists(location)) mod.Location = location;
  633. mod.ContainingAssembly = module.ContainingAssembly;
  634. modRefs[i].Module = mod;
  635. modules.Add(new ModuleReference(name, mod));
  636. nextModRef: ;
  637. }
  638. }
  639. private static string ReadSerString(MemoryCursor/*!*/ sigReader)
  640. {
  641. int n = sigReader.ReadCompressedInt();
  642. if (n < 0) return null;
  643. return sigReader.ReadUTF8(n);
  644. }
  645. private void AddFieldsToType(TypeNode/*!*/ type, FieldRow[]/*!*/ fieldDefs, FieldPtrRow[]/*!*/ fieldPtrs, int start, int end)
  646. {
  647. for (int i = start; i < end; i++)
  648. {
  649. int ii = i;
  650. if (fieldPtrs.Length > 0) ii = fieldPtrs[i - 1].Field;
  651. Field field = this.GetFieldFromDef(ii, type);
  652. if (field != null) type.Members.Add(field);
  653. }
  654. }
  655. private void GetUnderlyingTypeOfEnumNode(EnumNode /*!*/enumNode, FieldRow[]/*!*/ fieldDefs, FieldPtrRow[]/*!*/ fieldPtrs, int start, int end)
  656. {
  657. TypeNode underlyingType = null;
  658. for (int i = start; i < end; i++)
  659. {
  660. int ii = i;
  661. if (fieldPtrs.Length > 0) ii = fieldPtrs[i - 1].Field;
  662. FieldRow fld = fieldDefs[ii - 1];
  663. if (fld.Field != null && !fld.Field.IsStatic)
  664. {
  665. underlyingType = fld.Field.Type;
  666. break;
  667. }
  668. FieldFlags fieldFlags = (FieldFlags)fld.Flags;
  669. if ((fieldFlags & FieldFlags.Static) == 0)
  670. {
  671. this.tables.GetSignatureLength(fld.Signature);
  672. MemoryCursor sigReader = this.tables.GetNewCursor();
  673. GetAndCheckSignatureToken(6, sigReader);
  674. underlyingType = this.ParseTypeSignature(sigReader);
  675. break;
  676. }
  677. }
  678. enumNode.underlyingType = underlyingType;
  679. }
  680. private void AddMethodsToType(TypeNode/*!*/ type, MethodPtrRow[]/*!*/ methodPtrs, int start, int end)
  681. //^ requires type.members != null;
  682. {
  683. for (int i = start; i < end; i++)
  684. {
  685. int ii = i;
  686. if (methodPtrs.Length > 0) ii = methodPtrs[i - 1].Method;
  687. Method method = this.GetMethodFromDef(ii, type);
  688. if (method != null && ((method.Flags & MethodFlags.RTSpecialName) == 0 || method.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey))
  689. type.members.Add(method);
  690. }
  691. }
  692. private void AddMoreStuffToParameters(Method method, ParameterList parameters, int start, int end)
  693. {
  694. ParamRow[] pars = this.tables.ParamTable;
  695. int n = parameters == null ? 0 : parameters.Count;
  696. for (int i = start; i < end; i++)
  697. {
  698. ParamRow pr = pars[i - 1];
  699. if (pr.Sequence == 0 && method != null)
  700. {
  701. //The parameter entry with sequence 0 is used as a target for custom attributes that apply to the return value
  702. method.ReturnAttributes = this.GetCustomAttributesFor((i << 5) | 4);
  703. if ((pr.Flags & (int)ParameterFlags.HasFieldMarshal) != 0)
  704. method.ReturnTypeMarshallingInformation = this.GetMarshallingInformation((i << 1) | 1);
  705. this.AddMoreStuffToParameters(null, parameters, start + 1, end);
  706. return;
  707. }
  708. int j = pr.Sequence;
  709. if (j < 1 || j > n) continue; //Bad metadata, ignore
  710. if (parameters == null) continue;
  711. Parameter par = parameters[j - 1];
  712. par.Attributes = this.GetCustomAttributesFor((i << 5) | 4);
  713. par.Flags = (ParameterFlags)pr.Flags;
  714. if ((par.Flags & ParameterFlags.HasDefault) != 0)
  715. par.DefaultValue = this.GetLiteral((i << 2) | 1, par.Type);
  716. if ((par.Flags & ParameterFlags.HasFieldMarshal) != 0)
  717. par.MarshallingInformation = this.GetMarshallingInformation((i << 1) | 1);
  718. par.Name = tables.GetIdentifier(pr.Name);
  719. }
  720. }
  721. private void AddPropertiesToType(TypeNode/*!*/ type, PropertyRow[]/*!*/ propertyDefs, PropertyPtrRow[]/*!*/ propertyPtrs, int start, int end)
  722. //requires type.members != null;
  723. {
  724. MetadataReader tables = this.tables;
  725. for (int i = start; i < end; i++)
  726. {
  727. int ii = i;
  728. if (propertyPtrs.Length > 0) ii = propertyPtrs[i - 1].Property;
  729. PropertyRow prop = propertyDefs[ii - 1];
  730. Property property = new Property();
  731. property.Attributes = this.GetCustomAttributesFor((ii << 5) | 9);
  732. property.DeclaringType = type;
  733. property.Flags = (PropertyFlags)prop.Flags;
  734. property.Name = tables.GetIdentifier(prop.Name);
  735. if ((property.Flags & PropertyFlags.RTSpecialName) == 0 || property.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)
  736. {
  737. this.AddMethodsToProperty(ii, property);
  738. type.members.Add(property);
  739. }
  740. //REVIEW: the signature seems to be redundant. Is there any point in retrieving it?
  741. }
  742. }
  743. private void AddMethodsToProperty(int propIndex, Property/*!*/ property)
  744. {
  745. int codedPropIndex = (propIndex << 1) | 1;
  746. MetadataReader tables = this.tables;
  747. MethodRow[] methods = tables.MethodTable;
  748. MethodSemanticsRow[] methodSemantics = tables.MethodSemanticsTable;
  749. int i = 0, n = methodSemantics.Length, j = n - 1;
  750. bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodSemantics) % 2 == 1;
  751. if (sorted)
  752. {
  753. while (i < j)
  754. {
  755. int k = (i + j) / 2;
  756. if (methodSemantics[k].Association < codedPropIndex)
  757. i = k + 1;
  758. else
  759. j = k;
  760. }
  761. while (i > 0 && methodSemantics[i - 1].Association == codedPropIndex) i--;
  762. }
  763. for (; i < n; i++)
  764. {
  765. MethodSemanticsRow meth = methodSemantics[i];
  766. Method propertyMethod = methods[meth.Method - 1].Method;
  767. if (propertyMethod == null) continue;
  768. if (meth.Association == codedPropIndex)
  769. {
  770. propertyMethod.DeclaringMember = property;
  771. switch (meth.Semantics)
  772. {
  773. case 0x0001: property.Setter = propertyMethod; break;
  774. case 0x0002: property.Getter = propertyMethod; break;
  775. default:
  776. if (property.OtherMethods == null) property.OtherMethods = new MethodList();
  777. property.OtherMethods.Add(propertyMethod); break;
  778. }
  779. }
  780. else if (sorted)
  781. break;
  782. }
  783. }
  784. private void AddEventsToType(TypeNode/*!*/ type, EventRow[]/*!*/ eventDefs, EventPtrRow[]/*!*/ eventPtrs, int start, int end)
  785. {
  786. MetadataReader tables = this.tables;
  787. for (int i = start; i < end; i++)
  788. {
  789. int ii = i;
  790. if (eventPtrs.Length > 0) ii = eventPtrs[i].Event;
  791. EventRow ev = eventDefs[ii - 1];
  792. Event evnt = new Event();
  793. evnt.Attributes = this.GetCustomAttributesFor((ii << 5) | 10);
  794. evnt.DeclaringType = type;
  795. evnt.Flags = (EventFlags)ev.Flags;
  796. evnt.HandlerType = this.DecodeAndGetTypeDefOrRefOrSpec(ev.EventType);
  797. evnt.Name = tables.GetIdentifier(ev.Name);
  798. if ((evnt.Flags & EventFlags.RTSpecialName) == 0 || evnt.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)
  799. {
  800. this.AddMethodsToEvent(ii, evnt);
  801. type.Members.Add(evnt);
  802. }
  803. }
  804. }
  805. private void AddMethodsToEvent(int eventIndex, Event/*!*/ evnt)
  806. {
  807. int codedEventIndex = eventIndex << 1;
  808. MetadataReader tables = this.tables;
  809. MethodRow[] methods = tables.MethodTable;
  810. MethodSemanticsRow[] methodSemantics = tables.MethodSemanticsTable;
  811. int i = 0, n = methodSemantics.Length, j = n - 1;
  812. bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodSemantics) % 2 == 1;
  813. if (sorted)
  814. {
  815. while (i < j)
  816. {
  817. int k = (i + j) / 2;
  818. if (methodSemantics[k].Association < codedEventIndex)
  819. i = k + 1;
  820. else
  821. j = k;
  822. }
  823. while (i > 0 && methodSemantics[i - 1].Association == codedEventIndex) i--;
  824. }
  825. MethodFlags handlerFlags = (MethodFlags)0;
  826. for (; i < n; i++)
  827. {
  828. MethodSemanticsRow meth = methodSemantics[i];
  829. Method eventMethod = methods[meth.Method - 1].Method;
  830. if (eventMethod == null) continue;
  831. if (meth.Association == codedEventIndex)
  832. {
  833. eventMethod.DeclaringMember = evnt;
  834. switch (meth.Semantics)
  835. {
  836. case 0x0008: evnt.HandlerAdder = eventMethod; handlerFlags = eventMethod.Flags; break;
  837. case 0x0010: evnt.HandlerRemover = eventMethod; handlerFlags = eventMethod.Flags; break;
  838. case 0x0020: evnt.HandlerCaller = eventMethod; break;
  839. default:
  840. if (evnt.OtherMethods == null) evnt.OtherMethods = new MethodList();
  841. evnt.OtherMethods.Add(eventMethod); break;
  842. }
  843. }
  844. else if (sorted)
  845. break;
  846. }
  847. evnt.HandlerFlags = handlerFlags;
  848. }
  849. private bool TypeDefOrRefOrSpecIsClass(int codedIndex)
  850. {
  851. if (codedIndex == 0) return false;
  852. switch (codedIndex & 0x3)
  853. {
  854. case 0x00: return this.TypeDefIsClass(codedIndex >> 2);
  855. case 0x01: TypeNode t = this.GetTypeFromRef(codedIndex >> 2); return t is Class;
  856. case 0x02: return this.TypeSpecIsClass(codedIndex >> 2);
  857. }
  858. throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
  859. }
  860. private bool TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(int codedIndex)
  861. {
  862. if (codedIndex == 0) return false;
  863. switch (codedIndex & 0x3)
  864. {
  865. case 0x00: return this.TypeDefIsClassButNotValueTypeBaseClass(codedIndex >> 2);
  866. case 0x01:
  867. TypeNode t = this.GetTypeFromRef(codedIndex >> 2);
  868. return t != CoreSystemTypes.ValueType && t != CoreSystemTypes.Enum && t is Class;
  869. case 0x02: return this.TypeSpecIsClass(codedIndex >> 2);
  870. }
  871. throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
  872. }
  873. private TypeNode DecodeAndGetTypeDefOrRefOrSpec(int codedIndex)
  874. {
  875. if (codedIndex == 0) return null;
  876. switch (codedIndex & 0x3)
  877. {
  878. case 0x00: return this.GetTypeFromDef(codedIndex >> 2);
  879. case 0x01: return this.GetTypeFromRef(codedIndex >> 2);
  880. case 0x02: return this.GetTypeFromSpec(codedIndex >> 2);
  881. }
  882. throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
  883. }
  884. private TypeNode DecodeAndGetTypeDefOrRefOrSpec(int codedIndex, bool expectStruct)
  885. {
  886. if (codedIndex == 0) return null;
  887. switch (codedIndex & 0x3)
  888. {
  889. case 0x00: return this.GetTypeFromDef(codedIndex >> 2);
  890. case 0x01: return this.GetTypeFromRef(codedIndex >> 2, expectStruct);
  891. case 0x02: return this.GetTypeFromSpec(codedIndex >> 2);
  892. }
  893. throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
  894. }
  895. private TypeNode GetTypeIfNotGenericInstance(int codedIndex)
  896. {
  897. if (codedIndex == 0) return null;
  898. switch (codedIndex & 0x3)
  899. {
  900. case 0x00: return this.GetTypeFromDef(codedIndex >> 2);
  901. case 0x01: return this.GetTypeFromRef(codedIndex >> 2, false);
  902. }
  903. return null;
  904. }
  905. internal AssemblyNode/*!*/ GetAssemblyFromReference(AssemblyReference/*!*/ assemblyReference)
  906. {
  907. lock (this)
  908. {
  909. if (SystemAssemblyLocation.ParsedAssembly != null && (assemblyReference.Name == "mscorlib" || assemblyReference.Name == "basetypes" || assemblyReference.Name == "ioconfig"
  910. || assemblyReference.Name == "singularity.v1"))
  911. return SystemAssemblyLocation.ParsedAssembly;
  912. if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assemblyReference.Name) return CoreSystemTypes.SystemAssembly;
  913. string strongName = null;
  914. object cachedValue = null;
  915. if (assemblyReference.PublicKeyOrToken == null || assemblyReference.PublicKeyOrToken.Length == 0)
  916. {
  917. if (assemblyReference.Location != null)
  918. cachedValue = this.localAssemblyCache[assemblyReference.Location];
  919. if (cachedValue == null)
  920. {
  921. cachedValue = this.localAssemblyCache[assemblyReference.Name];
  922. if (cachedValue != null && assemblyReference.Location != null)
  923. this.localAssemblyCache[assemblyReference.Location] = cachedValue;
  924. }
  925. }
  926. else
  927. {
  928. strongName = assemblyReference.StrongName;
  929. if (this.useStaticCache)
  930. {
  931. //See if reference is to an assembly that lives in the GAC.
  932. if (assemblyReference.Location != null)
  933. cachedValue = Reader.StaticAssemblyCache[assemblyReference.Location];
  934. if (cachedValue == null)
  935. cachedValue = Reader.StaticAssemblyCache[strongName];
  936. }
  937. if (cachedValue == null)
  938. cachedValue = this.localAssemblyCache[strongName];
  939. }
  940. if (cachedValue == null)
  941. {
  942. //See if assembly is a platform assembly (and apply unification)
  943. AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(assemblyReference.Name).UniqueIdKey];
  944. if (aRef != null && assemblyReference.Version != null && aRef.Version >= assemblyReference.Version && aRef.MatchesIgnoringVersion(assemblyReference))
  945. {
  946. AssemblyNode platformAssembly = aRef.assembly;
  947. if (platformAssembly == null)
  948. {
  949. Debug.Assert(aRef.Location != null);
  950. platformAssembly = AssemblyNode.GetAssembly(aRef.Location, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  951. }
  952. if (platformAssembly != null)
  953. {
  954. if (strongName == null) strongName = assemblyReference.Name;
  955. lock (Reader.StaticAssemblyCache)
  956. {
  957. if (aRef.Location != null)
  958. Reader.StaticAssemblyCache[aRef.Location] = platformAssembly;
  959. Reader.StaticAssemblyCache[strongName] = platformAssembly;
  960. }
  961. return aRef.assembly = platformAssembly;
  962. }
  963. }
  964. }
  965. AssemblyNode assembly = cachedValue as AssemblyNode;
  966. if (assembly != null) goto done;
  967. //No cached assembly and no cached reader for this assembly. Look for a resolver.
  968. if (this.module != null)
  969. {
  970. assembly = this.module.Resolve(assemblyReference);
  971. if (assembly != null)
  972. {
  973. if (strongName == null)
  974. {
  975. this.localAssemblyCache[assembly.Name] = assembly;
  976. if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly;
  977. }
  978. else
  979. {
  980. if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assembly.Name) return CoreSystemTypes.SystemAssembly;
  981. lock (Reader.StaticAssemblyCache)
  982. {
  983. if (this.useStaticCache)
  984. {
  985. if (assembly.Location != null)
  986. Reader.StaticAssemblyCache[assembly.Location] = assembly;
  987. Reader.StaticAssemblyCache[strongName] = assembly;
  988. }
  989. else
  990. {
  991. this.localAssemblyCache[strongName] = assembly;
  992. if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly;
  993. }
  994. }
  995. }
  996. goto done;
  997. }
  998. }
  999. //Look for an assembly with the given name in the same directory as the referencing module
  1000. if (this.directory != null)
  1001. {
  1002. string fileName = System.IO.Path.Combine(this.directory, assemblyReference.Name + ".dll");
  1003. if (System.IO.File.Exists(fileName))
  1004. {
  1005. assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  1006. if (assembly != null)
  1007. {
  1008. if (strongName == null) goto cacheIt; //found something
  1009. //return assembly only if it matches the strong name of the reference
  1010. if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt;
  1011. }
  1012. }
  1013. fileName = System.IO.Path.Combine(this.directory, assemblyReference.Name + ".exe");
  1014. if (System.IO.File.Exists(fileName))
  1015. {
  1016. assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  1017. if (assembly != null)
  1018. {
  1019. if (strongName == null) goto cacheIt; //found something
  1020. //return assembly only if it matches the strong name of the reference
  1021. if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt;
  1022. }
  1023. }
  1024. fileName = System.IO.Path.Combine(this.directory, assemblyReference.Name + ".ill");
  1025. if (System.IO.File.Exists(fileName))
  1026. {
  1027. assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  1028. if (assembly != null)
  1029. {
  1030. if (strongName == null) goto cacheIt; //found something
  1031. //return assembly only if it matches the strong name of the reference
  1032. if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt;
  1033. }
  1034. }
  1035. }
  1036. //Look for an assembly in the same directory as the application using Reader.
  1037. {
  1038. string fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyReference.Name + ".dll");
  1039. if (System.IO.File.Exists(fileName))
  1040. {
  1041. assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  1042. if (assembly != null)
  1043. {
  1044. if (strongName == null) goto cacheIt; //found something
  1045. //return assembly only if it matches the strong name of the reference
  1046. if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt;
  1047. }
  1048. }
  1049. fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyReference.Name + ".exe");
  1050. if (System.IO.File.Exists(fileName))
  1051. {
  1052. assembly = AssemblyNode.GetAssembly(fileName, this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  1053. if (assembly != null)
  1054. {
  1055. if (strongName == null) goto cacheIt; //found something
  1056. //return assembly only if it matches the strong name of the reference
  1057. if (assemblyReference.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken)) goto cacheIt;
  1058. }
  1059. }
  1060. }
  1061. assembly = null;
  1062. //Probe the GAC
  1063. string gacLocation = null;
  1064. if (strongName != null)
  1065. {
  1066. //Look for the assembly in the system's Global Assembly Cache
  1067. gacLocation = GlobalAssemblyCache.GetLocation(assemblyReference);
  1068. if (gacLocation != null && gacLocation.Length == 0) gacLocation = null;
  1069. if (gacLocation != null)
  1070. {
  1071. assembly = AssemblyNode.GetAssembly(gacLocation, this.useStaticCache ? Reader.StaticAssemblyCache : this.localAssemblyCache, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
  1072. if (assembly != null)
  1073. {
  1074. lock (Reader.StaticAssemblyCache)
  1075. {
  1076. if (this.useStaticCache)
  1077. {
  1078. Reader.StaticAssemblyCache[gacLocation] = assembly;
  1079. Reader.StaticAssemblyCache[strongName] = assembly;
  1080. }
  1081. else
  1082. {
  1083. this.localAssemblyCache[gacLocation] = assembly;
  1084. this.localAssemblyCache[strongName] = assembly;
  1085. }
  1086. }
  1087. }
  1088. }
  1089. }
  1090. goto done;
  1091. cacheIt:
  1092. if (strongName == null)
  1093. {
  1094. this.localAssemblyCache[assembly.Name] = assembly;
  1095. if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly;
  1096. }
  1097. else
  1098. {
  1099. this.localAssemblyCache[strongName] = assembly;
  1100. if (assembly.Location != null) this.localAssemblyCache[assembly.Location] = assembly;
  1101. }
  1102. done:
  1103. if (assembly != null)
  1104. assembly.InitializeAssemblyReferenceResolution(this.module);
  1105. if (assembly == null)
  1106. {
  1107. if (this.module != null)
  1108. {
  1109. assembly = this.module.ResolveAfterProbingFailed(assemblyReference);
  1110. if (assembly != null) goto cacheIt;
  1111. HandleError(this.module, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.AssemblyReferenceNotResolved, assemblyReference.StrongName));
  1112. }
  1113. assembly = new AssemblyNode();
  1114. assembly.Culture = assemblyReference.Culture;
  1115. assembly.Name = assemblyReference.Name;
  1116. assembly.PublicKeyOrToken = assemblyReference.PublicKeyOrToken;
  1117. assembly.Version = assemblyReference.Version;
  1118. assembly.Location = "unknown:location";
  1119. goto cacheIt;
  1120. }
  1121. return assembly;
  1122. }
  1123. }
  1124. private static void GetAndCheckSignatureToken(int expectedToken, MemoryCursor/*!*/ sigReader)
  1125. {
  1126. int tok = sigReader.ReadCompressedInt();
  1127. if (tok != expectedToken) throw new InvalidMetadataException(ExceptionStrings.MalformedSignature);
  1128. }
  1129. private Method GetConstructorDefOrRef(int codedIndex, out TypeNodeList varArgTypes)
  1130. {
  1131. varArgTypes = null;
  1132. switch (codedIndex & 0x7)
  1133. {
  1134. case 0x02: return this.GetMethodFromDef(codedIndex >> 3);
  1135. case 0x03: return (Method)this.GetMemberFromRef(codedIndex >> 3, out varArgTypes);
  1136. }
  1137. throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken);
  1138. }
  1139. private void GetResources(Module/*!*/ module)
  1140. {
  1141. ManifestResourceRow[] manifestResourceTable = this.tables.ManifestResourceTable;
  1142. int n = manifestResourceTable.Length;
  1143. ResourceList resources = new ResourceList();
  1144. for (int i = 0; i < n; i++)
  1145. {
  1146. ManifestResourceRow mrr = manifestResourceTable[i];
  1147. Resource r = new Resource();
  1148. r.Name = this.tables.GetString(mrr.Name);
  1149. r.IsPublic = (mrr.Flags & 7) == 1;
  1150. int impl = mrr.Implementation;
  1151. if (impl != 0)
  1152. {
  1153. switch (impl & 0x3)
  1154. {
  1155. case 0x0:
  1156. string modName = this.tables.GetString(this.tables.FileTable[(impl >> 2) - 1].Name);
  1157. if ((this.tables.FileTable[(impl >> 2) - 1].Flags & (int)FileFlags.ContainsNoMetaData) != 0)
  1158. {
  1159. r.DefiningModule = new Module();
  1160. r.DefiningModule.Directory = module.Directory;
  1161. r.DefiningModule.Location = Path.Combine(module.Directory, modName);
  1162. r.DefiningModule.Name = modName;
  1163. r.DefiningModule.Kind = ModuleKind.ManifestResourceFile;
  1164. r.DefiningModule.ContainingAssembly = module.ContainingAssembly;
  1165. r.DefiningModule.HashValue = this.tables.GetBlob(this.tables.FileTable[(impl >> 2) - 1].HashValue);
  1166. }
  1167. else
  1168. {
  1169. string modLocation = modName;
  1170. r.DefiningModule = GetNestedModule(module, modName, ref modLocation);
  1171. }
  1172. break;
  1173. case 0x1:
  1174. r.DefiningModule = this.tables.AssemblyRefTable[(impl >> 2) - 1].AssemblyReference.Assembly;
  1175. break;
  1176. }
  1177. }
  1178. else
  1179. {
  1180. r.DefiningModule = module;
  1181. r.Data = this.tables.GetResourceData(mrr.Offset);
  1182. }
  1183. resources.Add(r);
  1184. }
  1185. module.Resources = resources;
  1186. module.Win32Resources = this.tables.ReadWin32Resources();
  1187. }
  1188. private SecurityAttribute GetSecurityAttribute(int i)
  1189. {
  1190. DeclSecurityRow dsr = this.tables.DeclSecurityTable[i];
  1191. SecurityAttribute attr = new SecurityAttribute();
  1192. attr.Action = (System.Security.Permissions.SecurityAction)dsr.Action;
  1193. if (this.module.MetadataFormatMajorVersion > 1 || this.module.MetadataFormatMinorVersion > 0)
  1194. {
  1195. attr.PermissionAttributes = this.GetPermissionAttributes(dsr.PermissionSet, attr.Action);
  1196. if (attr.PermissionAttributes != null) return attr;
  1197. }
  1198. attr.SerializedPermissions = (string)this.tables.GetBlobString(dsr.PermissionSet);
  1199. return attr;
  1200. }
  1201. private AttributeList GetPermissionAttributes(int blobIndex, System.Security.Permissions.SecurityAction action)
  1202. {
  1203. AttributeList result = new AttributeList();
  1204. int blobLength;
  1205. MemoryCursor sigReader = this.tables.GetBlobCursor(blobIndex, out blobLength);
  1206. if (blobLength == 0) return null;
  1207. byte header = sigReader.ReadByte();
  1208. if (header != (byte)'*')
  1209. {
  1210. if (header == (byte)'<') return null;
  1211. if (header == (byte)'.') return this.GetPermissionAttributes2(blobIndex, action);
  1212. HandleError(this.module, ExceptionStrings.BadSecurityPermissionSetBlob);
  1213. return null;
  1214. }
  1215. sigReader.ReadInt32(); //Skip over the token for the attribute target
  1216. sigReader.ReadInt32(); //Skip over the security action
  1217. int numAttrs = sigReader.ReadInt32();
  1218. for (int i = 0; i < numAttrs; i++)
  1219. result.Add(this.GetPermissionAttribute(sigReader));
  1220. return result;
  1221. }
  1222. private AttributeNode GetPermissionAttribute(MemoryCursor/*!*/ sigReader)
  1223. {
  1224. sigReader.ReadInt32(); //Skip over index
  1225. int typeNameLength = sigReader.ReadInt32();
  1226. sigReader.ReadUTF8(typeNameLength); //Skip over type name
  1227. int constructorToken = sigReader.ReadInt32();
  1228. sigReader.ReadInt32(); //Skip over attribute type token
  1229. sigReader.ReadInt32(); //Skip over assembly ref token
  1230. int caBlobLength = sigReader.ReadInt32();
  1231. sigReader.ReadInt32(); //Skip over the number of parameters in the CA blob
  1232. TypeNodeList varArgTypes; //Ignored because vararg constructors are not allowed in Custom Attributes
  1233. Method cons = this.GetConstructorDefOrRef(constructorToken, out varArgTypes);
  1234. if (cons == null) cons = new Method();
  1235. return this.GetCustomAttribute(cons, sigReader, caBlobLength);
  1236. }
  1237. private AttributeList GetPermissionAttributes2(int blobIndex, System.Security.Permissions.SecurityAction action)
  1238. {
  1239. AttributeList result = new AttributeList();
  1240. int blobLength;
  1241. MemoryCursor sigReader = this.tables.GetBlobCursor(blobIndex, out blobLength);
  1242. if (blobLength == 0) return null;
  1243. byte header = sigReader.ReadByte();
  1244. if (header != (byte)'.')
  1245. {
  1246. HandleError(this.module, ExceptionStrings.BadSecurityPermissionSetBlob);
  1247. return null;
  1248. }
  1249. int numAttrs = sigReader.ReadCompressedInt();
  1250. for (int i = 0; i < numAttrs; i++)
  1251. result.Add(this.GetPermissionAttribute2(sigReader, action));
  1252. return result;
  1253. }
  1254. private AttributeNode GetPermissionAttribute2(MemoryCursor/*!*/ sigReader, System.Security.Permissions.SecurityAction action)
  1255. {
  1256. int typeNameLength = sigReader.ReadCompressedInt();
  1257. string serializedTypeName = sigReader.ReadUTF8(typeNameLength);
  1258. TypeNode attrType = null;
  1259. try
  1260. {
  1261. attrType = this.GetTypeFromSerializedName(serializedTypeName);
  1262. }
  1263. catch (InvalidMetadataException) { }
  1264. if (attrType == null)
  1265. {
  1266. HandleError(this.module, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.CouldNotResolveType, serializedTypeName));
  1267. return null;
  1268. }
  1269. InstanceInitializer cons = attrType.GetConstructor(CoreSystemTypes.SecurityAction);
  1270. if (cons == null)
  1271. {
  1272. HandleError(this.module, String.Format(CultureInfo.CurrentCulture,
  1273. ExceptionStrings.SecurityAttributeTypeDoesNotHaveADefaultConstructor, serializedTypeName));
  1274. return null;
  1275. }
  1276. sigReader.ReadCompressedInt(); //caBlobLength
  1277. int numProps = sigReader.ReadCompressedInt(); //Skip over the number of properties in the CA blob
  1278. ExpressionList arguments = new ExpressionList();
  1279. arguments.Add(new Literal(action, CoreSystemTypes.SecurityAction));
  1280. this.GetCustomAttributeNamedArguments(arguments, (ushort)numProps, sigReader);
  1281. return new AttributeNode(new MemberBinding(null, cons), arguments);
  1282. }
  1283. private static void HandleError(Module mod, string errorMessage)
  1284. {
  1285. if (mod != null)
  1286. {
  1287. if (mod.MetadataImportErrors == null) mod.MetadataImportErrors = new ArrayList();
  1288. mod.MetadataImportErrors.Add(new InvalidMetadataException(errorMessage));
  1289. }
  1290. }
  1291. private AttributeNode GetCustomAttribute(int i)
  1292. {
  1293. CustomAttributeRow ca = this.tables.CustomAttributeTable[i];
  1294. TypeNodeList varArgTypes; //Ignored because vararg constructors are not allowed in Custom Attributes
  1295. Method cons = this.GetConstructorDefOrRef(ca.Constructor, out varArgTypes);
  1296. if (cons == null) cons = new Method();
  1297. int blobLength;
  1298. MemoryCursor sigReader = this.tables.GetBlobCursor(ca.Value, out blobLength);
  1299. return this.GetCustomAttribute(cons, sigReader, blobLength);
  1300. }
  1301. private AttributeNode GetCustomAttribute(Method/*!*/ cons, MemoryCursor/*!*/ sigReader, int blobLength)
  1302. {
  1303. AttributeNode attr = new AttributeNode();
  1304. attr.Constructor = new MemberBinding(null, cons);
  1305. int n = cons.Parameters == null ? 0 : cons.Parameters.Count;
  1306. ExpressionList arguments = attr.Expressions = new ExpressionList();
  1307. int posAtBlobStart = sigReader.Position;
  1308. sigReader.ReadUInt16(); //Prolog
  1309. for (int j = 0; j < n; j++)
  1310. {
  1311. TypeNode t = TypeNode.StripModifiers(cons.Parameters[j].Type);
  1312. if (t == null) continue;
  1313. TypeNode/*!*/ pt = t;
  1314. object val = null;
  1315. try
  1316. {
  1317. val = this.GetCustomAttributeLiteralValue(sigReader, ref pt);
  1318. }
  1319. catch (Exception e)
  1320. {
  1321. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  1322. this.module.MetadataImportErrors.Add(e);
  1323. }
  1324. Literal lit = val as Literal;
  1325. if (lit == null) lit = new Literal(val, pt);
  1326. arguments.Add(lit);
  1327. }
  1328. if (sigReader.Position + 1 < posAtBlobStart + blobLength)
  1329. {
  1330. ushort numNamed = sigReader.ReadUInt16();
  1331. this.GetCustomAttributeNamedArguments(arguments, numNamed, sigReader);
  1332. }
  1333. return attr;
  1334. }
  1335. private void GetCustomAttributeNamedArguments(ExpressionList/*!*/ arguments, ushort numNamed, MemoryCursor/*!*/ sigReader)
  1336. {
  1337. for (int j = 0; j < numNamed; j++)
  1338. {
  1339. int nameTag = sigReader.ReadByte();
  1340. bool mustBox = sigReader.Byte(0) == (byte)ElementType.BoxedEnum;
  1341. TypeNode/*!*/ vType = this.ParseTypeSignature(sigReader);
  1342. Identifier id = sigReader.ReadIdentifierFromSerString();
  1343. object val = this.GetCustomAttributeLiteralValue(sigReader, ref vType);
  1344. Literal lit = val as Literal;
  1345. if (lit == null) lit = new Literal(val, vType);
  1346. NamedArgument narg = new NamedArgument(id, lit);
  1347. narg.Type = vType;
  1348. narg.IsCustomAttributeProperty = nameTag == 0x54;
  1349. narg.ValueIsBoxed = mustBox;
  1350. arguments.Add(narg);
  1351. }
  1352. }
  1353. private object GetCustomAttributeLiteralValue(MemoryCursor/*!*/ sigReader, TypeNode/*!*/ type)
  1354. {
  1355. TypeNode/*!*/ t = type;
  1356. object result = this.GetCustomAttributeLiteralValue(sigReader, ref t);
  1357. EnumNode enumType = t as EnumNode;
  1358. if (enumType != null && type == CoreSystemTypes.Object) result = new Literal(result, enumType);
  1359. return result;
  1360. }
  1361. private object GetCustomAttributeLiteralValue(MemoryCursor/*!*/ sigReader, ref TypeNode/*!*/ type)
  1362. {
  1363. if (type == null) return sigReader.ReadInt32();
  1364. switch (type.typeCode)
  1365. {
  1366. case ElementType.Boolean: return sigReader.ReadBoolean();
  1367. case ElementType.Char: return sigReader.ReadChar();
  1368. case ElementType.Double: return sigReader.ReadDouble();
  1369. case ElementType.Single: return sigReader.ReadSingle();
  1370. case ElementType.Int16: return sigReader.ReadInt16();
  1371. case ElementType.Int32: return sigReader.ReadInt32();
  1372. case ElementType.Int64: return sigReader.ReadInt64();
  1373. case ElementType.Int8: return sigReader.ReadSByte();
  1374. case ElementType.UInt16: return sigReader.ReadUInt16();
  1375. case ElementType.UInt32: return sigReader.ReadUInt32();
  1376. case ElementType.UInt64: return sigReader.ReadUInt64();
  1377. case ElementType.UInt8: return sigReader.ReadByte();
  1378. case ElementType.String: return ReadSerString(sigReader);
  1379. case ElementType.ValueType:
  1380. EnumNode etype = GetCustomAttributeEnumNode(ref type);
  1381. return this.GetCustomAttributeLiteralValue(sigReader, etype.UnderlyingType);
  1382. case ElementType.Class: return this.GetTypeFromSerializedName(ReadSerString(sigReader));
  1383. case ElementType.SzArray:
  1384. int numElems = sigReader.ReadInt32();
  1385. TypeNode elemType = ((ArrayType)type).ElementType;
  1386. return this.GetCustomAttributeLiteralArray(sigReader, numElems, elemType);
  1387. case ElementType.Object:
  1388. {
  1389. type = this.ParseTypeSignature(sigReader);
  1390. return this.GetCustomAttributeLiteralValue(sigReader, ref type);
  1391. }
  1392. }
  1393. throw new InvalidMetadataException(ExceptionStrings.UnexpectedTypeInCustomAttribute);
  1394. }
  1395. private static EnumNode/*!*/ GetCustomAttributeEnumNode(ref TypeNode/*!*/ type)
  1396. {
  1397. EnumNode etype = ((TypeNode)type) as EnumNode;
  1398. if (etype == null || etype.UnderlyingType == null)
  1399. {
  1400. //Happens when type is declared in a assembly that has not been resolved. In that case only the type name
  1401. //and the fact that it is a value type is known. There is no completely safe recovery from it, but at this point we
  1402. //can fake up an enum with Int32 as underlying type. This works in most situations.
  1403. etype = new EnumNode();
  1404. etype.Name = type.Name;
  1405. etype.Namespace = type.Namespace;
  1406. etype.DeclaringModule = type.DeclaringModule;
  1407. etype.UnderlyingType = CoreSystemTypes.Int32;
  1408. type = etype;
  1409. }
  1410. return etype;
  1411. }
  1412. private Array GetCustomAttributeLiteralArray(MemoryCursor/*!*/ sigReader, int numElems, TypeNode/*!*/ elemType)
  1413. {
  1414. Array array = this.ConstructCustomAttributeLiteralArray(numElems, elemType);
  1415. for (int i = 0; i < numElems; i++)
  1416. {
  1417. object elem = this.GetCustomAttributeLiteralValue(sigReader, elemType);
  1418. array.SetValue(elem, i);
  1419. }
  1420. return array;
  1421. }
  1422. private Array ConstructCustomAttributeLiteralArray(int numElems, TypeNode/*!*/ elemType)
  1423. {
  1424. if (numElems == -1) return null;
  1425. if (numElems < 0) throw new InvalidMetadataException(ExceptionStrings.UnexpectedTypeInCustomAttribute);
  1426. switch (elemType.typeCode)
  1427. {
  1428. case ElementType.Boolean: return new Boolean[numElems];
  1429. case ElementType.Char: return new Char[numElems];
  1430. case ElementType.Double: return new Double[numElems];
  1431. case ElementType.Single: return new Single[numElems];
  1432. case ElementType.Int16: return new Int16[numElems];
  1433. case ElementType.Int32: return new Int32[numElems];
  1434. case ElementType.Int64: return new Int64[numElems];
  1435. case ElementType.Int8: return new SByte[numElems];
  1436. case ElementType.UInt16: return new UInt16[numElems];
  1437. case ElementType.UInt32: return new UInt32[numElems];
  1438. case ElementType.UInt64: return new UInt64[numElems];
  1439. case ElementType.UInt8: return new Byte[numElems];
  1440. case ElementType.String: return new String[numElems];
  1441. // Only enum value types are legal in attribute instances as stated in section 17.1.3 of the C# 1.0 spec
  1442. case ElementType.ValueType:
  1443. TypeNode/*!*/ elType = elemType;
  1444. EnumNode eType = GetCustomAttributeEnumNode(ref elType);
  1445. return this.ConstructCustomAttributeLiteralArray(numElems, eType.UnderlyingType);
  1446. // This needs to be a TypeNode since GetCustomAttributeLiteralValue will return a Struct if the Type is a value type
  1447. case ElementType.Class: return new TypeNode[numElems];
  1448. // REVIEW: Is this the right exception? Is this the right exception string?
  1449. // Multi-dimensional arrays are not legal in attribute instances according section 17.1.3 of the C# 1.0 spec
  1450. case ElementType.SzArray: throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken);
  1451. case ElementType.Object: return new Object[numElems];
  1452. }
  1453. throw new InvalidMetadataException(ExceptionStrings.UnexpectedTypeInCustomAttribute);
  1454. }
  1455. //TODO: rewrite this entire mess using a proper grammar based parser
  1456. private TypeNode/*!*/ GetTypeFromSerializedName(string serializedName)
  1457. {
  1458. if (serializedName == null) return null;
  1459. string assemblyName = null;
  1460. string typeName = serializedName;
  1461. int firstComma = FindFirstCommaOutsideBrackets(serializedName);
  1462. if (firstComma > 0)
  1463. {
  1464. int i = 1;
  1465. while (firstComma + i < serializedName.Length && serializedName[firstComma + i] == ' ') i++;
  1466. assemblyName = serializedName.Substring(firstComma + i);
  1467. typeName = serializedName.Substring(0, firstComma);
  1468. }
  1469. return this.GetTypeFromSerializedName(typeName, assemblyName);
  1470. }
  1471. private static int FindFirstCommaOutsideBrackets(string/*!*/ serializedName)
  1472. {
  1473. int numBrackets = 0;
  1474. int numAngles = 0;
  1475. for (int i = 0, n = serializedName == null ? 0 : serializedName.Length; i < n; i++)
  1476. {
  1477. char ch = serializedName[i];
  1478. if (ch == '[')
  1479. numBrackets++;
  1480. else if (ch == ']')
  1481. {
  1482. if (--numBrackets < 0) return -1;
  1483. }
  1484. else if (ch == '<')
  1485. numAngles++;
  1486. else if (ch == '>')
  1487. {
  1488. if (--numAngles < 0) return -1;
  1489. }
  1490. else if (ch == ',' && numBrackets == 0 && numAngles == 0)
  1491. return i;
  1492. }
  1493. return -1;
  1494. }
  1495. private TypeNode/*!*/ GetTypeFromSerializedName(string/*!*/ typeName, string assemblyName)
  1496. {
  1497. string/*!*/ nspace, name;
  1498. int i;
  1499. ParseTypeName(typeName, out nspace, out name, out i);
  1500. Module tMod = null;
  1501. TypeNode t = this.LookupType(nspace, name, assemblyName, out tMod);
  1502. if (t == null)
  1503. {
  1504. if (i < typeName.Length && typeName[i] == '!')
  1505. {
  1506. int codedIndex = 0;
  1507. if (PlatformHelpers.TryParseInt32(typeName.Substring(0, i), out codedIndex))
  1508. {
  1509. t = this.DecodeAndGetTypeDefOrRefOrSpec(codedIndex);
  1510. if (t != null) return t;
  1511. }
  1512. }
  1513. t = this.GetDummyTypeNode(Identifier.For(nspace), Identifier.For(name), tMod, null, false);
  1514. }
  1515. if (i >= typeName.Length) return t;
  1516. char ch = typeName[i];
  1517. if (ch == '+') return this.GetTypeFromSerializedName(typeName.Substring(i + 1), t);
  1518. if (ch == '&') return t.GetReferenceType();
  1519. if (ch == '*') return t.GetPointerType();
  1520. if (ch == '[') return this.ParseArrayOrGenericType(typeName.Substring(i + 1, typeName.Length - 1 - i), t);
  1521. throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName);
  1522. }
  1523. private TypeNode/*!*/ GetTypeFromSerializedName(string/*!*/ typeName, TypeNode/*!*/ nestingType)
  1524. {
  1525. string/*!*/ name;
  1526. int i = 0;
  1527. ParseSimpleTypeName(typeName, out name, ref i);
  1528. TypeNode t = nestingType.GetNestedType(Identifier.For(name));
  1529. if (t == null)
  1530. t = this.GetDummyTypeNode(Identifier.Empty, Identifier.For(name), nestingType.DeclaringModule, nestingType, false);
  1531. if (i >= typeName.Length) return t;
  1532. char ch = typeName[i];
  1533. if (ch == '+') return this.GetTypeFromSerializedName(typeName.Substring(i + 1), t);
  1534. if (ch == '&') return t.GetReferenceType();
  1535. if (ch == '*') return t.GetPointerType();
  1536. if (ch == '[') return this.ParseArrayOrGenericType(typeName.Substring(i + 1, typeName.Length - 1 - i), t);
  1537. throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName);
  1538. }
  1539. private TypeNode/*!*/ ParseArrayOrGenericType(string typeName, TypeNode/*!*/ rootType)
  1540. {
  1541. if (typeName == null || rootType == null) { Debug.Assert(false); return rootType; }
  1542. //Get here after "rootType[" has been parsed. What follows is either an array type specifier or some generic type arguments.
  1543. if (typeName.Length == 0)
  1544. throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName); //Something ought to follow the [
  1545. if (typeName[0] == ']')
  1546. { //Single dimensional array with zero lower bound
  1547. if (typeName.Length == 1) return rootType.GetArrayType(1);
  1548. if (typeName[1] == '[' && typeName.Length > 2)
  1549. return this.ParseArrayOrGenericType(typeName.Substring(2), rootType.GetArrayType(1));
  1550. throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName);
  1551. }
  1552. if (typeName[0] == '*')
  1553. { //Single dimensional array with unknown lower bound
  1554. if (typeName.Length > 1 && typeName[1] == ']')
  1555. {
  1556. if (typeName.Length == 2) return rootType.GetArrayType(1, true);
  1557. if (typeName[2] == '[' && typeName.Length > 3)
  1558. return this.ParseArrayOrGenericType(typeName.Substring(3), rootType.GetArrayType(1, true));
  1559. }
  1560. throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName);
  1561. }
  1562. if (typeName[0] == ',')
  1563. { //Muti dimensional array
  1564. int rank = 1;
  1565. while (rank < typeName.Length && typeName[rank] == ',') rank++;
  1566. if (rank < typeName.Length && typeName[rank] == ']')
  1567. {
  1568. if (typeName.Length == rank + 1) return rootType.GetArrayType(rank + 1);
  1569. if (typeName[rank + 1] == '[' && typeName.Length > rank + 2)
  1570. return this.ParseArrayOrGenericType(typeName.Substring(rank + 2), rootType.GetArrayType(rank));
  1571. }
  1572. throw new InvalidMetadataException(ExceptionStrings.BadSerializedTypeName);
  1573. }
  1574. //Generic type instance
  1575. int offset = 0;
  1576. if (typeName[0] == '[') offset = 1; //Assembly qualified type name forming part of a generic parameter list
  1577. TypeNodeList arguments = new TypeNodeList();
  1578. int commaPos = FindFirstCommaOutsideBrackets(typeName);
  1579. while (commaPos > 1)
  1580. {
  1581. arguments.Add(this.GetTypeFromSerializedName(typeName.Substring(offset, commaPos - offset)));
  1582. typeName = typeName.Substring(commaPos + 1);
  1583. offset = typeName[0] == '[' ? 1 : 0;
  1584. commaPos = FindFirstCommaOutsideBrackets(typeName);
  1585. }
  1586. //Find the position of the first unbalanced ].
  1587. int lastCharPos = offset;
  1588. for (int leftBracketCount = 0; lastCharPos < typeName.Length; lastCharPos++)
  1589. {
  1590. char ch = typeName[lastCharPos];
  1591. if (ch == '[') leftBracketCount++;
  1592. else if (ch == ']')
  1593. {
  1594. leftBracketCount--;
  1595. if (leftBracketCount < 0) break;
  1596. }
  1597. }
  1598. arguments.Add(this.GetTypeFromSerializedName(typeName.Substring(offset, lastCharPos - offset)));
  1599. TypeNode retVal = rootType.GetGenericTemplateInstance(this.module, arguments);
  1600. if (lastCharPos + 1 < typeName.Length && typeName[lastCharPos + 1] == ']')
  1601. lastCharPos++;
  1602. if (lastCharPos + 1 < typeName.Length)
  1603. {
  1604. //The generic type is complete, but there is yet more to the type
  1605. char ch = typeName[lastCharPos + 1];
  1606. if (ch == '+') retVal = this.GetTypeFromSerializedName(typeName.Substring(lastCharPos + 2), retVal);
  1607. if (ch == '&') retVal = retVal.GetReferenceType();
  1608. if (ch == '*') retVal = retVal.GetPointerType();
  1609. if (ch == '[') retVal = this.ParseArrayOrGenericType(typeName.Substring(lastCharPos + 2, typeName.Length - 1 - lastCharPos - 1), retVal);
  1610. }
  1611. return retVal;
  1612. }
  1613. private static void ParseSimpleTypeName(string/*!*/ source, out string/*!*/ name, ref int i)
  1614. {
  1615. int n = source.Length;
  1616. int start = i;
  1617. for (; i < n; i++)
  1618. {
  1619. char ch = source[i];
  1620. if (ch == '\\') { i++; continue; }
  1621. if (ch == '.' || ch == '+' || ch == '&' || ch == '*' || ch == '[' || ch == '!') break;
  1622. if (ch == '<')
  1623. {
  1624. int unmatched = 1;
  1625. while (unmatched > 0 && ++i < n)
  1626. {
  1627. ch = source[i];
  1628. if (ch == '\\') i++;
  1629. else if (ch == '<') unmatched++;
  1630. else if (ch == '>') unmatched--;
  1631. }
  1632. }
  1633. }
  1634. if (i < n)
  1635. name = source.Substring(start, i - start);
  1636. else
  1637. name = source.Substring(start);
  1638. }
  1639. private static void ParseTypeName(string/*!*/ source, out string/*!*/ nspace, out string/*!*/ name, out int i)
  1640. {
  1641. i = 0;
  1642. int n = source.Length;
  1643. nspace = string.Empty;
  1644. while (true)
  1645. {
  1646. int start = i;
  1647. ParseSimpleTypeName(source, out name, ref i);
  1648. if (i < n && source[i] == '.') { i++; continue; }
  1649. if (start != 0) nspace = source.Substring(0, start - 1);
  1650. return;
  1651. }
  1652. }
  1653. private TypeNode LookupType(string/*!*/ nameSpace, string/*!*/ name, string assemblyName, out Module module)
  1654. {
  1655. Identifier namespaceId = Identifier.For(nameSpace);
  1656. Identifier nameId = Identifier.For(name);
  1657. module = this.module;
  1658. //^ assume module != null;
  1659. if (assemblyName == null)
  1660. {
  1661. TypeNode t = module.GetType(namespaceId, nameId);
  1662. if (t != null) return t;
  1663. module = CoreSystemTypes.SystemAssembly;
  1664. return CoreSystemTypes.SystemAssembly.GetType(namespaceId, nameId);
  1665. }
  1666. //See if the type is in one of the assemblies explicitly referenced by the current module
  1667. AssemblyReferenceList arefs = module.AssemblyReferences;
  1668. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
  1669. {
  1670. AssemblyReference aref = arefs[i];
  1671. if (aref != null && aref.StrongName == assemblyName && aref.Assembly != null)
  1672. {
  1673. module = aref.Assembly;
  1674. return aref.Assembly.GetType(namespaceId, nameId);
  1675. }
  1676. }
  1677. //Construct an assembly reference and probe for it
  1678. AssemblyReference aRef = new AssemblyReference(assemblyName);
  1679. AssemblyNode referringAssembly = this.module as AssemblyNode;
  1680. if (referringAssembly != null && (referringAssembly.Flags & AssemblyFlags.Retargetable) != 0)
  1681. aRef.Flags |= AssemblyFlags.Retargetable;
  1682. AssemblyNode aNode = this.GetAssemblyFromReference(aRef);
  1683. if (aNode != null)
  1684. {
  1685. module = aNode;
  1686. TypeNode result = aNode.GetType(namespaceId, nameId);
  1687. return result;
  1688. }
  1689. return null;
  1690. }
  1691. private void GetCustomAttributesFor(Module/*!*/ module)
  1692. {
  1693. try
  1694. {
  1695. if (this.tables.entryPointToken != 0)
  1696. module.EntryPoint = (Method)this.GetMemberFromToken(this.tables.entryPointToken);
  1697. else
  1698. module.EntryPoint = Module.NoSuchMethod;
  1699. if (module.NodeType == NodeType.Module)
  1700. {
  1701. module.Attributes = this.GetCustomAttributesFor((1 << 5) | 7);
  1702. return;
  1703. }
  1704. AssemblyNode assembly = (AssemblyNode)module;
  1705. assembly.SecurityAttributes = this.GetSecurityAttributesFor((1 << 2) | 2);
  1706. assembly.Attributes = this.GetCustomAttributesFor((1 << 5) | 14);
  1707. assembly.ModuleAttributes = this.GetCustomAttributesFor((1 << 5) | 7);
  1708. }
  1709. catch (Exception e)
  1710. {
  1711. if(this.module == null)
  1712. return;
  1713. if(this.module.MetadataImportErrors == null)
  1714. this.module.MetadataImportErrors = new ArrayList();
  1715. this.module.MetadataImportErrors.Add(e);
  1716. module.Attributes = new AttributeList();
  1717. }
  1718. }
  1719. private AttributeList/*!*/ GetCustomAttributesFor(int parentIndex)
  1720. {
  1721. CustomAttributeRow[] customAttributes = this.tables.CustomAttributeTable;
  1722. AttributeList attributes = new AttributeList();
  1723. try
  1724. {
  1725. int i = 0, n = customAttributes.Length, j = n - 1;
  1726. if (n == 0) return attributes;
  1727. bool sorted = (this.sortedTablesMask >> (int)TableIndices.CustomAttribute) % 2 == 1;
  1728. if (sorted)
  1729. {
  1730. while (i < j)
  1731. {
  1732. int k = (i + j) / 2;
  1733. if (customAttributes[k].Parent < parentIndex)
  1734. i = k + 1;
  1735. else
  1736. j = k;
  1737. }
  1738. while (i > 0 && customAttributes[i - 1].Parent == parentIndex) i--;
  1739. }
  1740. for (; i < n; i++)
  1741. if (customAttributes[i].Parent == parentIndex)
  1742. attributes.Add(this.GetCustomAttribute(i));
  1743. else if (sorted)
  1744. break;
  1745. }
  1746. catch (Exception e)
  1747. {
  1748. if (this.module == null) return attributes;
  1749. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  1750. this.module.MetadataImportErrors.Add(e);
  1751. }
  1752. return attributes;
  1753. }
  1754. private SecurityAttributeList GetSecurityAttributesFor(int parentIndex)
  1755. {
  1756. DeclSecurityRow[] securityAttributes = this.tables.DeclSecurityTable;
  1757. SecurityAttributeList attributes = new SecurityAttributeList();
  1758. try
  1759. {
  1760. int i = 0, n = securityAttributes.Length, j = n - 1;
  1761. if (n == 0) return attributes;
  1762. bool sorted = (this.sortedTablesMask >> (int)TableIndices.DeclSecurity) % 2 == 1;
  1763. if (sorted)
  1764. {
  1765. while (i < j)
  1766. {
  1767. int k = (i + j) / 2;
  1768. if (securityAttributes[k].Parent < parentIndex)
  1769. i = k + 1;
  1770. else
  1771. j = k;
  1772. }
  1773. while (i > 0 && securityAttributes[i - 1].Parent == parentIndex) i--;
  1774. }
  1775. for (; i < n; i++)
  1776. if (securityAttributes[i].Parent == parentIndex)
  1777. attributes.Add(this.GetSecurityAttribute(i));
  1778. else if (sorted)
  1779. break;
  1780. }
  1781. catch (Exception e)
  1782. {
  1783. if (this.module == null) return attributes;
  1784. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  1785. this.module.MetadataImportErrors.Add(e);
  1786. }
  1787. return attributes;
  1788. }
  1789. private void GetTypeParameterConstraints(int parentIndex, TypeNodeList parameters)
  1790. {
  1791. if (parameters == null) return;
  1792. GenericParamRow[] genericParameters = this.tables.GenericParamTable;
  1793. int i = 0, n = genericParameters.Length, j = n - 1;
  1794. bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParam) % 2 == 1;
  1795. if (sorted)
  1796. {
  1797. while (i < j)
  1798. {
  1799. int k = (i + j) / 2;
  1800. if (genericParameters[k].Owner < parentIndex)
  1801. i = k + 1;
  1802. else
  1803. j = k;
  1804. }
  1805. while (i > 0 && genericParameters[i - 1].Owner == parentIndex) i--;
  1806. }
  1807. for (int k = 0; i < n && k < parameters.Count; i++, k++)
  1808. if (genericParameters[i].Owner == parentIndex)
  1809. {
  1810. TypeNode gp = parameters[k];
  1811. this.GetGenericParameterConstraints(i, ref gp);
  1812. parameters[k] = gp;
  1813. }
  1814. else if (sorted)
  1815. break;
  1816. }
  1817. private TypeNodeList GetTypeParametersFor(int parentIndex, Member parent)
  1818. {
  1819. GenericParamRow[] genericParameters = this.tables.GenericParamTable;
  1820. TypeNodeList types = new TypeNodeList();
  1821. int i = 0, n = genericParameters.Length, j = n - 1;
  1822. bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParam) % 2 == 1;
  1823. if (sorted)
  1824. {
  1825. while (i < j)
  1826. {
  1827. int k = (i + j) / 2;
  1828. if (genericParameters[k].Owner < parentIndex)
  1829. i = k + 1;
  1830. else
  1831. j = k;
  1832. }
  1833. while (i > 0 && genericParameters[i - 1].Owner == parentIndex) i--;
  1834. }
  1835. for (int index = 0; i < n; i++, index++)
  1836. if (genericParameters[i].Owner == parentIndex)
  1837. types.Add(this.GetGenericParameter(i, index, parent));
  1838. else if (sorted)
  1839. break;
  1840. if (types.Count == 0) return null;
  1841. return types;
  1842. }
  1843. private TypeNode GetGenericParameter(int index, int parameterListIndex, Member parent)
  1844. {
  1845. GenericParamRow[] genericParameters = this.tables.GenericParamTable;
  1846. GenericParamRow gpr = genericParameters[index++];
  1847. string name = this.tables.GetString(gpr.Name);
  1848. GenericParamConstraintRow[] genericParameterConstraints = this.tables.GenericParamConstraintTable;
  1849. bool isClass = false;
  1850. int i = 0, n = genericParameterConstraints.Length, j = n - 1;
  1851. bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParamConstraint) % 2 == 1;
  1852. if (sorted)
  1853. {
  1854. while (i < j)
  1855. {
  1856. int k = (i + j) / 2;
  1857. if (genericParameterConstraints[k].Param < index)
  1858. i = k + 1;
  1859. else
  1860. j = k;
  1861. }
  1862. while (i > 0 && genericParameterConstraints[i - 1].Param == index) i--;
  1863. }
  1864. for (; i < n && !isClass; i++)
  1865. {
  1866. if (genericParameterConstraints[i].Param == index)
  1867. {
  1868. isClass = this.TypeDefOrRefOrSpecIsClass(genericParameterConstraints[i].Constraint);
  1869. }
  1870. else if (sorted)
  1871. break;
  1872. }
  1873. if (isClass)
  1874. {
  1875. ClassParameter cp = parent is Method ? new MethodClassParameter() : new ClassParameter();
  1876. cp.DeclaringMember = parent;
  1877. cp.ParameterListIndex = parameterListIndex;
  1878. cp.Name = Identifier.For(name);
  1879. cp.DeclaringModule = this.module;
  1880. cp.TypeParameterFlags = (TypeParameterFlags)gpr.Flags;
  1881. return cp;
  1882. }
  1883. TypeParameter tp = parent is Method ? new MethodTypeParameter() : new TypeParameter();
  1884. tp.DeclaringMember = parent;
  1885. tp.ParameterListIndex = parameterListIndex;
  1886. tp.Name = Identifier.For(name);
  1887. tp.DeclaringModule = this.module;
  1888. tp.TypeParameterFlags = (TypeParameterFlags)gpr.Flags;
  1889. return tp;
  1890. }
  1891. private void GetGenericParameterConstraints(int index, ref TypeNode/*!*/ parameter)
  1892. {
  1893. Debug.Assert(parameter != null);
  1894. index++;
  1895. GenericParamConstraintRow[] genericParameterConstraints = this.tables.GenericParamConstraintTable;
  1896. TypeNodeList constraints = new TypeNodeList();
  1897. Class baseClass = null;
  1898. InterfaceList interfaces = new InterfaceList();
  1899. int i = 0, n = genericParameterConstraints.Length, j = n - 1;
  1900. bool sorted = (this.sortedTablesMask >> (int)TableIndices.GenericParamConstraint) % 2 == 1;
  1901. if (sorted)
  1902. {
  1903. while (i < j)
  1904. {
  1905. int k = (i + j) / 2;
  1906. if (genericParameterConstraints[k].Param < index)
  1907. i = k + 1;
  1908. else
  1909. j = k;
  1910. }
  1911. while (i > 0 && genericParameterConstraints[i - 1].Param == index) i--;
  1912. }
  1913. for (; i < n; i++)
  1914. {
  1915. if (genericParameterConstraints[i].Param == index)
  1916. {
  1917. TypeNode t = this.DecodeAndGetTypeDefOrRefOrSpec(genericParameterConstraints[i].Constraint);
  1918. Class c = t as Class;
  1919. if (c != null)
  1920. baseClass = c;
  1921. else if (t is Interface)
  1922. interfaces.Add((Interface)t);
  1923. constraints.Add(t);
  1924. }
  1925. else if (sorted)
  1926. break;
  1927. }
  1928. ClassParameter cp = parameter as ClassParameter;
  1929. if (cp == null && baseClass != null)
  1930. {
  1931. cp = ((ITypeParameter)parameter).DeclaringMember is Method ? new MethodClassParameter() : new ClassParameter();
  1932. cp.Name = parameter.Name;
  1933. cp.DeclaringMember = ((ITypeParameter)parameter).DeclaringMember;
  1934. cp.ParameterListIndex = ((ITypeParameter)parameter).ParameterListIndex;
  1935. cp.DeclaringModule = this.module;
  1936. cp.TypeParameterFlags = ((ITypeParameter)parameter).TypeParameterFlags;
  1937. parameter = cp;
  1938. }
  1939. if (cp != null)
  1940. cp.structuralElementTypes = constraints;
  1941. else
  1942. ((TypeParameter)parameter).structuralElementTypes = constraints;
  1943. if (baseClass != null && cp != null) cp.BaseClass = baseClass;
  1944. parameter.Interfaces = interfaces;
  1945. }
  1946. internal static Block/*!*/ GetOrCreateBlock(TrivialHashtable/*!*/ blockMap, int address)
  1947. {
  1948. Block block = (Block)blockMap[address + 1];
  1949. if (block == null)
  1950. {
  1951. blockMap[address + 1] = block = new Block(new StatementList());
  1952. block.SourceContext.StartPos = address;
  1953. }
  1954. return block;
  1955. }
  1956. internal Field GetFieldFromDef(int i)
  1957. {
  1958. return this.GetFieldFromDef(i, null);
  1959. }
  1960. internal Field GetFieldFromDef(int i, TypeNode declaringType)
  1961. {
  1962. FieldRow[] fieldDefs = this.tables.FieldTable;
  1963. FieldRow fld = fieldDefs[i - 1];
  1964. if (fld.Field != null) return fld.Field;
  1965. Field field = new Field();
  1966. fieldDefs[i - 1].Field = field;
  1967. field.Attributes = this.GetCustomAttributesFor((i << 5) | 1);
  1968. field.Flags = (FieldFlags)fld.Flags;
  1969. field.Name = tables.GetIdentifier(fld.Name);
  1970. if ((field.Flags & FieldFlags.RTSpecialName) != 0 && field.Name.UniqueIdKey == StandardIds._Deleted.UniqueIdKey) return null;
  1971. tables.GetSignatureLength(fld.Signature); //sigLength
  1972. MemoryCursor sigReader = this.tables.GetNewCursor();
  1973. GetAndCheckSignatureToken(6, sigReader);
  1974. field.Type = this.ParseTypeSignature(sigReader);
  1975. RequiredModifier reqMod = field.Type as RequiredModifier;
  1976. if (reqMod != null && reqMod.Modifier == CoreSystemTypes.IsVolatile)
  1977. {
  1978. field.IsVolatile = true;
  1979. field.Type = reqMod.ModifiedType;
  1980. }
  1981. if ((field.Flags & FieldFlags.HasDefault) != 0)
  1982. field.DefaultValue = this.GetLiteral(i << 2, field.Type);
  1983. if ((field.Flags & FieldFlags.HasFieldMarshal) != 0)
  1984. field.MarshallingInformation = this.GetMarshallingInformation((i << 1) | 0);
  1985. if ((field.Flags & FieldFlags.HasFieldRVA) != 0)
  1986. field.InitialData = this.GetInitialData(i, field.Type, out field.section);
  1987. if (declaringType == null)
  1988. {
  1989. TypeDefRow[] typeDefs = this.tables.TypeDefTable;
  1990. int indx = i;
  1991. FieldPtrRow[] fieldPtrs = this.tables.FieldPtrTable;
  1992. int n = fieldPtrs.Length;
  1993. for (int j = 0; j < n; j++)
  1994. {
  1995. if (fieldPtrs[j].Field == i)
  1996. {
  1997. indx = j + 1; break;
  1998. }
  1999. }
  2000. n = typeDefs.Length;
  2001. for (int j = n - 1; j >= 0; j--)
  2002. { //TODO: binary search
  2003. TypeDefRow tdr = typeDefs[j];
  2004. if (tdr.FieldList <= indx)
  2005. {
  2006. declaringType = this.GetTypeFromDef(j + 1);
  2007. break;
  2008. }
  2009. }
  2010. }
  2011. field.DeclaringType = declaringType;
  2012. if (declaringType != null && (declaringType.Flags & TypeFlags.ExplicitLayout) != 0)
  2013. {
  2014. FieldLayoutRow[] fieldLayouts = this.tables.FieldLayoutTable;
  2015. int n = fieldLayouts.Length;
  2016. for (int j = n - 1; j >= 0; j--)
  2017. { //TODO: binary search
  2018. FieldLayoutRow flr = fieldLayouts[j];
  2019. if (flr.Field == i)
  2020. {
  2021. field.Offset = flr.Offset;
  2022. break;
  2023. }
  2024. }
  2025. }
  2026. return field;
  2027. }
  2028. private byte[] GetInitialData(int fieldIndex, TypeNode fieldType, out PESection targetSection)
  2029. {
  2030. targetSection = PESection.Text;
  2031. FieldRvaRow[] fieldRvaTable = this.tables.FieldRvaTable;
  2032. bool sorted = (this.sortedTablesMask >> (int)TableIndices.FieldRva) % 2 == 1;
  2033. int i = 0, n = fieldRvaTable.Length, j = n - 1;
  2034. if (n == 0) return null;
  2035. if (sorted)
  2036. {
  2037. while (i < j)
  2038. {
  2039. int k = (i + j) / 2;
  2040. if (fieldRvaTable[k].Field < fieldIndex)
  2041. i = k + 1;
  2042. else
  2043. j = k;
  2044. }
  2045. }
  2046. else
  2047. for (; i < j; i++)
  2048. if (fieldRvaTable[i].Field == fieldIndex) break;
  2049. FieldRvaRow frr = fieldRvaTable[i];
  2050. if (frr.Field != fieldIndex) return null;
  2051. Field fld = this.tables.FieldTable[fieldIndex - 1].Field;
  2052. if (fld != null) fld.Offset = frr.RVA;
  2053. fieldType = TypeNode.StripModifiers(fieldType);
  2054. EnumNode enumType = fieldType as EnumNode;
  2055. if (enumType != null) fieldType = TypeNode.StripModifiers(enumType.UnderlyingType);
  2056. if (fieldType == null) { Debug.Fail(""); return null; }
  2057. int size = fieldType.ClassSize;
  2058. if (size <= 0)
  2059. {
  2060. switch (fieldType.typeCode)
  2061. {
  2062. case ElementType.Boolean: size = 1; break;
  2063. case ElementType.Char: size = 2; break;
  2064. case ElementType.Double: size = 8; break;
  2065. case ElementType.Int16: size = 2; break;
  2066. case ElementType.Int32: size = 4; break;
  2067. case ElementType.Int64: size = 8; break;
  2068. case ElementType.Int8: size = 1; break;
  2069. case ElementType.Single: size = 4; break;
  2070. case ElementType.UInt16: size = 2; break;
  2071. case ElementType.UInt32: size = 4; break;
  2072. case ElementType.UInt64: size = 8; break;
  2073. case ElementType.UInt8: size = 1; break;
  2074. default:
  2075. if (fieldType is Pointer || fieldType is FunctionPointer)
  2076. {
  2077. size = 4; break;
  2078. }
  2079. //TODO: this seems wrong
  2080. if (i < n - 1)
  2081. size = fieldRvaTable[i + 1].RVA - frr.RVA;
  2082. else if (targetSection != PESection.Text)
  2083. size = this.tables.GetOffsetToEndOfSection(frr.RVA);
  2084. break;
  2085. }
  2086. }
  2087. if (size <= 0) return null;
  2088. if (this.tables.NoOffsetFor(frr.RVA) || this.tables.NoOffsetFor(frr.RVA + size - 1))
  2089. return null;
  2090. MemoryCursor c = this.tables.GetNewCursor(frr.RVA, out targetSection);
  2091. byte[] result = new byte[size];
  2092. for (i = 0; i < size; i++)
  2093. result[i] = c.ReadByte();
  2094. return result;
  2095. }
  2096. private Literal GetLiteral(int parentCodedIndex, TypeNode/*!*/ type)
  2097. {
  2098. ConstantRow[] constants = this.tables.ConstantTable;
  2099. //TODO: do a binary search
  2100. for (int i = 0, n = constants.Length; i < n; i++)
  2101. {
  2102. if (constants[i].Parent != parentCodedIndex) continue;
  2103. object value = this.tables.GetValueFromBlob(constants[i].Type, constants[i].Value);
  2104. TypeCode valTypeCode = System.Convert.GetTypeCode(value);
  2105. TypeNode underlyingType = type;
  2106. if (type is EnumNode) underlyingType = ((EnumNode)type).UnderlyingType;
  2107. if (underlyingType.TypeCode != valTypeCode) type = CoreSystemTypes.Object;
  2108. if (type == CoreSystemTypes.Object && value != null)
  2109. {
  2110. switch (valTypeCode)
  2111. {
  2112. case TypeCode.Boolean: type = CoreSystemTypes.Boolean; break;
  2113. case TypeCode.Byte: type = CoreSystemTypes.UInt8; break;
  2114. case TypeCode.Char: type = CoreSystemTypes.Char; break;
  2115. case TypeCode.Double: type = CoreSystemTypes.Double; break;
  2116. case TypeCode.Int16: type = CoreSystemTypes.Int16; break;
  2117. case TypeCode.Int32: type = CoreSystemTypes.Int32; break;
  2118. case TypeCode.Int64: type = CoreSystemTypes.Int64; break;
  2119. case TypeCode.SByte: type = CoreSystemTypes.Int8; break;
  2120. case TypeCode.Single: type = CoreSystemTypes.Single; break;
  2121. case TypeCode.String: type = CoreSystemTypes.String; break;
  2122. case TypeCode.UInt16: type = CoreSystemTypes.UInt16; break;
  2123. case TypeCode.UInt32: type = CoreSystemTypes.UInt32; break;
  2124. case TypeCode.UInt64: type = CoreSystemTypes.UInt64; break;
  2125. case TypeCode.Empty:
  2126. case TypeCode.Object: type = CoreSystemTypes.Type; break;
  2127. }
  2128. }
  2129. return new Literal(value, type);
  2130. }
  2131. throw new InvalidMetadataException(ExceptionStrings.BadConstantParentIndex);
  2132. }
  2133. internal FunctionPointer GetCalliSignature(int ssigToken)
  2134. {
  2135. StandAloneSigRow ssr = this.tables.StandAloneSigTable[(ssigToken & 0xFFFFFF) - 1];
  2136. MemoryCursor sigReader = this.tables.GetBlobCursor(ssr.Signature);
  2137. return this.ParseFunctionPointer(sigReader);
  2138. }
  2139. internal void GetLocals(int localIndex, LocalList/*!*/ locals, Hashtable/*!*/ localSourceNames)
  2140. {
  2141. if (localIndex == 0) return;
  2142. StandAloneSigRow ssr = this.tables.StandAloneSigTable[(localIndex & 0xFFFFFF) - 1];
  2143. this.tables.GetSignatureLength(ssr.Signature);
  2144. MemoryCursor sigReader = this.tables.GetNewCursor();
  2145. if (sigReader.ReadByte() != 0x7) throw new InvalidMetadataException(ExceptionStrings.InvalidLocalSignature);
  2146. int count = sigReader.ReadCompressedInt();
  2147. for (int i = 0; i < count; i++)
  2148. {
  2149. string lookupName = (string)localSourceNames[i];
  2150. string name = lookupName == null ? "local" + i : lookupName;
  2151. bool pinned = false;
  2152. TypeNode locType = this.ParseTypeSignature(sigReader, ref pinned);
  2153. Local loc = new Local(Identifier.For(name), locType);
  2154. loc.Pinned = pinned;
  2155. locals.Add(loc);
  2156. }
  2157. }
  2158. internal void GetLocalSourceNames(ISymUnmanagedScope/*!*/ scope, Hashtable/*!*/ localSourceNames)
  2159. {
  2160. uint numLocals = scope.GetLocalCount();
  2161. IntPtr[] localPtrs = new IntPtr[numLocals];
  2162. scope.GetLocals((uint)localPtrs.Length, out numLocals, localPtrs);
  2163. char[] nameBuffer = new char[100];
  2164. uint nameLen;
  2165. for (int i = 0; i < numLocals; i++)
  2166. {
  2167. ISymUnmanagedVariable local =
  2168. (ISymUnmanagedVariable)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(localPtrs[i], typeof(ISymUnmanagedVariable));
  2169. if (local != null)
  2170. {
  2171. local.GetName((uint)nameBuffer.Length, out nameLen, nameBuffer);
  2172. int localIndex = (int)local.GetAddressField1();
  2173. localSourceNames[localIndex] = new String(nameBuffer, 0, (int)nameLen - 1);
  2174. System.Runtime.InteropServices.Marshal.ReleaseComObject(local);
  2175. }
  2176. System.Runtime.InteropServices.Marshal.Release(localPtrs[i]);
  2177. }
  2178. IntPtr[] subscopes = new IntPtr[100];
  2179. uint numScopes;
  2180. scope.GetChildren((uint)subscopes.Length, out numScopes, subscopes);
  2181. for (int i = 0; i < numScopes; i++)
  2182. {
  2183. ISymUnmanagedScope subscope =
  2184. (ISymUnmanagedScope)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(subscopes[i], typeof(ISymUnmanagedScope));
  2185. if (subscope != null)
  2186. {
  2187. this.GetLocalSourceNames(subscope, localSourceNames);
  2188. System.Runtime.InteropServices.Marshal.ReleaseComObject(subscope);
  2189. }
  2190. System.Runtime.InteropServices.Marshal.Release(subscopes[i]);
  2191. //TODO: need to figure out how map these scope to blocks and set HasLocals on those blocks
  2192. }
  2193. }
  2194. private MarshallingInformation GetMarshallingInformation(int parentCodedIndex)
  2195. {
  2196. FieldMarshalRow[] mtypes = this.tables.FieldMarshalTable;
  2197. bool sorted = (this.sortedTablesMask >> (int)TableIndices.FieldMarshal) % 2 == 1;
  2198. int i = 0, n = mtypes.Length, j = n - 1;
  2199. if (n == 0) return null;
  2200. if (sorted)
  2201. {
  2202. while (i < j)
  2203. {
  2204. int k = (i + j) / 2;
  2205. if (mtypes[k].Parent < parentCodedIndex)
  2206. i = k + 1;
  2207. else
  2208. j = k;
  2209. }
  2210. while (i > 0 && mtypes[i - 1].Parent == parentCodedIndex) i--;
  2211. }
  2212. else
  2213. for (; i < j; i++)
  2214. if (mtypes[i].Parent == parentCodedIndex) break;
  2215. FieldMarshalRow fmr = mtypes[i];
  2216. if (fmr.Parent != parentCodedIndex) return null;
  2217. MarshallingInformation result = new MarshallingInformation();
  2218. int blobSize = 0;
  2219. MemoryCursor c = this.tables.GetBlobCursor(fmr.NativeType, out blobSize);
  2220. int initialPosition = c.Position;
  2221. result.NativeType = (NativeType)c.ReadByte();
  2222. if (result.NativeType == NativeType.CustomMarshaler)
  2223. {
  2224. c.ReadUInt16(); //Skip over 0
  2225. result.Class = ReadSerString(c);
  2226. result.Cookie = ReadSerString(c);
  2227. }
  2228. else if (blobSize > 1)
  2229. {
  2230. if (result.NativeType == NativeType.LPArray)
  2231. {
  2232. result.ElementType = (NativeType)c.ReadByte();
  2233. result.ParamIndex = -1;
  2234. int bytesRead = 2;
  2235. if (bytesRead < blobSize)
  2236. {
  2237. int pos = c.Position;
  2238. result.ParamIndex = c.ReadCompressedInt();
  2239. bytesRead += c.Position - pos;
  2240. if (bytesRead < blobSize)
  2241. {
  2242. pos = c.Position;
  2243. result.ElementSize = c.ReadCompressedInt();
  2244. bytesRead += c.Position - pos;
  2245. if (bytesRead < blobSize)
  2246. result.NumberOfElements = c.ReadCompressedInt();
  2247. }
  2248. }
  2249. }
  2250. else if (result.NativeType == NativeType.SafeArray)
  2251. {
  2252. result.ElementType = (NativeType)c.ReadByte(); //Actually a variant type. TODO: what about VT_VECTOR VT_ARRAY and VT_BYREF?
  2253. if (c.Position < initialPosition + blobSize - 1)
  2254. result.Class = ReadSerString(c);
  2255. }
  2256. else
  2257. {
  2258. result.Size = c.ReadCompressedInt();
  2259. if (result.NativeType == NativeType.ByValArray)
  2260. {
  2261. if (blobSize > 2)
  2262. result.ElementType = (NativeType)c.ReadByte();
  2263. else
  2264. result.ElementType = NativeType.NotSpecified;
  2265. }
  2266. }
  2267. }
  2268. return result;
  2269. }
  2270. private void GetMethodBody(Method/*!*/ method, object/*!*/ i, bool asInstructionList)
  2271. {
  2272. if(asInstructionList)
  2273. {
  2274. this.GetMethodInstructions(method, i);
  2275. return;
  2276. }
  2277. TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters;
  2278. this.currentMethodTypeParameters = method.templateParameters;
  2279. TypeNode savedCurrentType = this.currentType;
  2280. this.currentType = method.DeclaringType;
  2281. try
  2282. {
  2283. MethodRow meth = this.tables.MethodTable[((int)i) - 1];
  2284. StatementList statements;
  2285. if(meth.RVA != 0 && (((MethodImplFlags)meth.ImplFlags) & MethodImplFlags.ManagedMask) == MethodImplFlags.Managed)
  2286. {
  2287. if(this.getDebugSymbols)
  2288. this.GetMethodDebugSymbols(method, 0x6000000 | (uint)(int)i);
  2289. statements = this.ParseMethodBody(method, (int)i, meth.RVA);
  2290. }
  2291. else
  2292. statements = new StatementList();
  2293. method.Body = new Block(statements);
  2294. method.Body.HasLocals = true;
  2295. }
  2296. catch(Exception e)
  2297. {
  2298. if(this.module != null)
  2299. {
  2300. if(this.module.MetadataImportErrors == null)
  2301. this.module.MetadataImportErrors = new ArrayList();
  2302. this.module.MetadataImportErrors.Add(e);
  2303. }
  2304. method.Body = new Block(new StatementList());
  2305. }
  2306. finally
  2307. {
  2308. this.currentMethodTypeParameters = savedCurrentMethodTypeParameters;
  2309. this.currentType = savedCurrentType;
  2310. }
  2311. }
  2312. private void GetMethodDebugSymbols(Method/*!*/ method, uint methodToken)
  2313. //^ requires this.debugReader != null;
  2314. {
  2315. ISymUnmanagedMethod methodInfo = null;
  2316. try
  2317. {
  2318. try
  2319. {
  2320. this.debugReader.GetMethod(methodToken, ref methodInfo);
  2321. method.RecordSequencePoints(methodInfo);
  2322. }
  2323. catch (COMException)
  2324. {
  2325. }
  2326. catch (InvalidCastException)
  2327. {
  2328. }
  2329. catch (System.Runtime.InteropServices.InvalidComObjectException) { }
  2330. }
  2331. finally
  2332. {
  2333. if (methodInfo != null)
  2334. Marshal.ReleaseComObject(methodInfo);
  2335. }
  2336. }
  2337. private void GetMethodInstructions(Method/*!*/ method, object/*!*/ i)
  2338. {
  2339. TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters;
  2340. this.currentMethodTypeParameters = method.templateParameters;
  2341. TypeNode savedCurrentType = this.currentType;
  2342. this.currentType = method.DeclaringType;
  2343. try
  2344. {
  2345. MethodRow meth = this.tables.MethodTable[((int)i) - 1];
  2346. if (meth.RVA != 0 && (((MethodImplFlags)meth.ImplFlags) & MethodImplFlags.ManagedMask) == MethodImplFlags.Managed)
  2347. {
  2348. if (this.getDebugSymbols) this.GetMethodDebugSymbols(method, 0x6000000 | (uint)(int)i);
  2349. method.Instructions = this.ParseMethodInstructions(method, (int)i, meth.RVA);
  2350. }
  2351. else
  2352. method.Instructions = new InstructionList();
  2353. }
  2354. catch (Exception e)
  2355. {
  2356. if (this.module != null)
  2357. {
  2358. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  2359. this.module.MetadataImportErrors.Add(e);
  2360. }
  2361. method.Instructions = new InstructionList();
  2362. }
  2363. finally
  2364. {
  2365. this.currentMethodTypeParameters = savedCurrentMethodTypeParameters;
  2366. this.currentType = savedCurrentType;
  2367. }
  2368. }
  2369. private Method GetMethodDefOrRef(int codedIndex)
  2370. {
  2371. switch (codedIndex & 0x1)
  2372. {
  2373. case 0x00: return this.GetMethodFromDef(codedIndex >> 1);
  2374. case 0x01:
  2375. TypeNodeList varArgTypes;
  2376. return (Method)this.GetMemberFromRef(codedIndex >> 1, out varArgTypes);
  2377. }
  2378. throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken);
  2379. }
  2380. private Method GetMethodDefOrRef(int codedIndex, int numberOfGenericArguments)
  2381. {
  2382. switch (codedIndex & 0x1)
  2383. {
  2384. case 0x00: return this.GetMethodFromDef(codedIndex >> 1);
  2385. case 0x01:
  2386. TypeNodeList varArgTypes;
  2387. return (Method)this.GetMemberFromRef(codedIndex >> 1, out varArgTypes, numberOfGenericArguments);
  2388. }
  2389. throw new InvalidMetadataException(ExceptionStrings.BadCustomAttributeTypeEncodedToken);
  2390. }
  2391. internal Method/*!*/ GetMethodFromDef(int index)
  2392. {
  2393. return this.GetMethodFromDef(index, null);
  2394. }
  2395. internal Method/*!*/ GetMethodFromDef(int index, TypeNode declaringType)
  2396. {
  2397. TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters;
  2398. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  2399. MethodRow[] methodDefs = this.tables.MethodTable;
  2400. MethodRow meth = methodDefs[index - 1];
  2401. if (meth.Method != null) return meth.Method;
  2402. if (declaringType == null)
  2403. {
  2404. int indx = index;
  2405. MethodPtrRow[] methodPtrs = this.tables.MethodPtrTable;
  2406. int n = methodPtrs.Length, i = 0, j = n - 1;
  2407. bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodPtr) % 2 == 1;
  2408. if (sorted)
  2409. {
  2410. while (i < j)
  2411. {
  2412. int k = (i + j) / 2;
  2413. if (methodPtrs[k].Method < index)
  2414. i = k + 1;
  2415. else
  2416. j = k;
  2417. }
  2418. while (i > 0 && methodPtrs[i - 1].Method == index) i--;
  2419. }
  2420. for (; i < n; i++)
  2421. {
  2422. if (methodPtrs[i].Method == index)
  2423. {
  2424. indx = i + 1; break;
  2425. }
  2426. }
  2427. TypeDefRow[] typeDefs = this.tables.TypeDefTable;
  2428. n = typeDefs.Length; i = 0; j = n - 1;
  2429. sorted = (this.sortedTablesMask >> (int)TableIndices.TypeDef) % 2 == 1;
  2430. if (sorted)
  2431. {
  2432. while (i < j)
  2433. {
  2434. int k = (i + j) / 2;
  2435. if (typeDefs[k].MethodList < indx)
  2436. i = k + 1;
  2437. else
  2438. j = k;
  2439. }
  2440. j = i;
  2441. while (j < n - 1 && typeDefs[j + 1].MethodList == indx) j++;
  2442. }
  2443. for (; j >= 0; j--)
  2444. {
  2445. if (typeDefs[j].MethodList <= indx)
  2446. {
  2447. declaringType = this.GetTypeFromDef(j + 1);
  2448. break;
  2449. }
  2450. }
  2451. }
  2452. Method.MethodBodyProvider provider = new Method.MethodBodyProvider(this.GetMethodBody);
  2453. Identifier name = tables.GetIdentifier(meth.Name);
  2454. Method method;
  2455. if ((((MethodFlags)meth.Flags) & MethodFlags.SpecialName) != 0 &&
  2456. (((MethodFlags)meth.Flags) & MethodFlags.SpecialName) != 0)
  2457. {
  2458. if (name.Name == ".ctor")
  2459. method = methodDefs[index - 1].Method = new InstanceInitializer(provider, index);
  2460. else if (name.Name == ".cctor")
  2461. method = methodDefs[index - 1].Method = new StaticInitializer(provider, index);
  2462. else
  2463. method = methodDefs[index - 1].Method = new Method(provider, index);
  2464. }
  2465. else
  2466. method = methodDefs[index - 1].Method = new Method(provider, index);
  2467. method.ProvideMethodAttributes = new Method.MethodAttributeProvider(this.GetMethodAttributes);
  2468. //method.Attributes = this.GetCustomAttributesFor((index << 5)|0); //TODO: get attributes lazily
  2469. method.Flags = (MethodFlags)meth.Flags;
  2470. method.ImplFlags = (MethodImplFlags)meth.ImplFlags;
  2471. method.Name = name;
  2472. if (declaringType != null && declaringType.IsGeneric)
  2473. {
  2474. if (declaringType.Template != null)
  2475. this.currentTypeParameters = declaringType.ConsolidatedTemplateArguments;
  2476. else
  2477. this.currentTypeParameters = declaringType.ConsolidatedTemplateParameters;
  2478. }
  2479. tables.GetSignatureLength(meth.Signature);
  2480. MemoryCursor sigReader = this.tables.GetNewCursor();
  2481. method.CallingConvention = (CallingConventionFlags)sigReader.ReadByte();
  2482. if (method.IsGeneric = (method.CallingConvention & CallingConventionFlags.Generic) != 0)
  2483. {
  2484. int numTemplateParameters = sigReader.ReadCompressedInt();
  2485. this.currentMethodTypeParameters = new TypeNodeList();
  2486. this.currentMethodTypeParameters = method.TemplateParameters = this.GetTypeParametersFor((index << 1) | 1, method);
  2487. this.GetTypeParameterConstraints((index << 1) | 1, method.TemplateParameters);
  2488. }
  2489. int numParams = sigReader.ReadCompressedInt();
  2490. method.ReturnType = this.ParseTypeSignature(sigReader);
  2491. if (declaringType != null && declaringType.IsValueType)
  2492. method.ThisParameter = new This(declaringType.GetReferenceType());
  2493. else
  2494. method.ThisParameter = new This(declaringType);
  2495. ParameterList paramList = method.Parameters = new ParameterList();
  2496. if(numParams > 0)
  2497. {
  2498. int offset = method.IsStatic ? 0 : 1;
  2499. for (int i = 0; i < numParams; i++)
  2500. {
  2501. Parameter param = new Parameter();
  2502. param.ParameterListIndex = i;
  2503. param.ArgumentListIndex = i + offset;
  2504. param.Type = this.ParseTypeSignature(sigReader);
  2505. param.DeclaringMethod = method;
  2506. paramList.Add(param);
  2507. }
  2508. int end = this.tables.ParamTable.Length + 1;
  2509. if (index < methodDefs.Length) end = methodDefs[index].ParamList;
  2510. this.AddMoreStuffToParameters(method, paramList, meth.ParamList, end);
  2511. for (int i = 0; i < numParams; i++)
  2512. {
  2513. Parameter param = paramList[i];
  2514. if (param.Name == null)
  2515. param.Name = Identifier.For("param" + (i));
  2516. }
  2517. }
  2518. else if (method.ReturnType != CoreSystemTypes.Void)
  2519. {
  2520. //check for custom attributes and marshaling information on return value
  2521. int i = meth.ParamList;
  2522. ParamPtrRow[] parPtrs = this.tables.ParamPtrTable; //TODO: why use ParamPtrTable in the branch and not the one above? Factor this out.
  2523. ParamRow[] pars = this.tables.ParamTable;
  2524. int n = methodDefs.Length;
  2525. int m = pars.Length;
  2526. if (index < n) m = methodDefs[index].ParamList - 1;
  2527. if (parPtrs.Length > 0)
  2528. {
  2529. if (pars != null && 0 < i && i <= m)
  2530. {
  2531. int j = parPtrs[i - 1].Param;
  2532. ParamRow pr = pars[j - 1];
  2533. if (pr.Sequence == 0)
  2534. this.AddMoreStuffToParameters(method, null, j, j + 1);
  2535. }
  2536. }
  2537. else
  2538. {
  2539. if (pars != null && 0 < i && i <= m)
  2540. {
  2541. ParamRow pr = pars[i - 1];
  2542. if (pr.Sequence == 0)
  2543. this.AddMoreStuffToParameters(method, null, i, i + 1);
  2544. }
  2545. }
  2546. }
  2547. //if ((method.Flags & MethodFlags.HasSecurity) != 0)
  2548. // method.SecurityAttributes = this.GetSecurityAttributesFor((index << 2)|1);
  2549. if ((method.Flags & MethodFlags.PInvokeImpl) != 0)
  2550. {
  2551. ImplMapRow[] implMaps = this.tables.ImplMapTable;
  2552. int n = implMaps.Length, i = 0, j = n - 1;
  2553. bool sorted = (this.sortedTablesMask >> (int)TableIndices.ImplMap) % 2 == 1;
  2554. if (sorted)
  2555. {
  2556. while (i < j)
  2557. {
  2558. int k = (i + j) / 2;
  2559. if ((implMaps[k].MemberForwarded >> 1) < index)
  2560. i = k + 1;
  2561. else
  2562. j = k;
  2563. }
  2564. while (i > 0 && (implMaps[i - 1].MemberForwarded >> 1) == index) i--;
  2565. }
  2566. for (; i < n; i++)
  2567. {
  2568. ImplMapRow imr = implMaps[i];
  2569. if (imr.MemberForwarded >> 1 == index)
  2570. {
  2571. method.PInvokeFlags = (PInvokeFlags)imr.MappingFlags;
  2572. method.PInvokeImportName = tables.GetString(imr.ImportName);
  2573. method.PInvokeModule = this.module.ModuleReferences[imr.ImportScope - 1].Module;
  2574. break;
  2575. }
  2576. }
  2577. }
  2578. method.DeclaringType = declaringType;
  2579. this.currentMethodTypeParameters = savedCurrentMethodTypeParameters;
  2580. this.currentTypeParameters = savedCurrentTypeParameters;
  2581. return method;
  2582. }
  2583. private void GetMethodAttributes(Method/*!*/ method, object/*!*/ handle)
  2584. {
  2585. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  2586. TypeNodeList savedCurrentMethodTypeParameters = this.currentMethodTypeParameters;
  2587. try
  2588. {
  2589. MetadataReader tables = this.tables;
  2590. int index = (int)handle;
  2591. MethodRow[] methodDefs = tables.MethodTable;
  2592. int n = methodDefs.Length;
  2593. if (index < 1 || index > n)
  2594. throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  2595. MethodRow md = methodDefs[index - 1];
  2596. if (method != md.Method) throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  2597. //Get custom attributes
  2598. method.Attributes = this.GetCustomAttributesFor((index << 5) | 0);
  2599. this.currentTypeParameters = savedCurrentTypeParameters;
  2600. this.currentMethodTypeParameters = savedCurrentMethodTypeParameters;
  2601. //Get security attributes
  2602. if ((method.Flags & MethodFlags.HasSecurity) != 0)
  2603. method.SecurityAttributes = this.GetSecurityAttributesFor((index << 2) | 1);
  2604. }
  2605. catch(Exception e)
  2606. {
  2607. if(this.module != null)
  2608. {
  2609. if(this.module.MetadataImportErrors == null)
  2610. this.module.MetadataImportErrors = new ArrayList();
  2611. this.module.MetadataImportErrors.Add(e);
  2612. }
  2613. method.Attributes = new AttributeList();
  2614. this.currentTypeParameters = savedCurrentTypeParameters;
  2615. this.currentMethodTypeParameters = savedCurrentMethodTypeParameters;
  2616. }
  2617. }
  2618. private Method/*!*/ GetMethodFromSpec(int i)
  2619. {
  2620. MethodSpecRow[] methodSpecs = this.tables.MethodSpecTable;
  2621. MethodSpecRow msr = methodSpecs[i - 1];
  2622. if (msr.InstantiatedMethod != null) return msr.InstantiatedMethod;
  2623. MemoryCursor sigReader = this.tables.GetBlobCursor(msr.Instantiation);
  2624. byte header = sigReader.ReadByte(); //skip over redundant header byte
  2625. Debug.Assert(header == 0x0a);
  2626. TypeNodeList templateArguments = this.ParseTypeList(sigReader);
  2627. Method template = this.GetMethodDefOrRef(msr.Method, templateArguments.Count);
  2628. if (template == null) return new Method();
  2629. if (template.TemplateParameters == null) return template; //Likely a dummy method
  2630. return template.GetTemplateInstance(this.currentType, templateArguments);
  2631. }
  2632. internal Member/*!*/ GetMemberFromToken(int tok)
  2633. {
  2634. TypeNodeList varArgTypes;
  2635. return this.GetMemberFromToken(tok, out varArgTypes);
  2636. }
  2637. internal Member/*!*/ GetMemberFromToken(int tok, out TypeNodeList varArgTypes)
  2638. {
  2639. varArgTypes = null;
  2640. Member member = null;
  2641. switch ((TableIndices)(tok >> 24))
  2642. {
  2643. case TableIndices.Field: member = this.GetFieldFromDef(tok & 0xFFFFFF); break;
  2644. case TableIndices.Method: member = this.GetMethodFromDef(tok & 0xFFFFFF); break;
  2645. case TableIndices.MemberRef: member = this.GetMemberFromRef(tok & 0xFFFFFF, out varArgTypes); break;
  2646. case TableIndices.TypeDef: member = this.GetTypeFromDef(tok & 0xFFFFFF); break;
  2647. case TableIndices.TypeRef: member = this.GetTypeFromRef(tok & 0xFFFFFF); break;
  2648. case TableIndices.TypeSpec: member = this.GetTypeFromSpec(tok & 0xFFFFFF); break;
  2649. case TableIndices.MethodSpec: member = this.GetMethodFromSpec(tok & 0xFFFFFF); break;
  2650. default: throw new InvalidMetadataException(ExceptionStrings.BadMemberToken);
  2651. }
  2652. if (member == null) throw new InvalidMetadataException(ExceptionStrings.BadMemberToken);
  2653. return member;
  2654. }
  2655. internal Member GetMemberFromRef(int i, out TypeNodeList varArgTypes)
  2656. {
  2657. return this.GetMemberFromRef(i, out varArgTypes, 0);
  2658. }
  2659. internal Member GetMemberFromRef(int i, out TypeNodeList varArgTypes, int numGenericArgs)
  2660. {
  2661. MemberRefRow mref = this.tables.MemberRefTable[i - 1];
  2662. if (mref.Member != null)
  2663. {
  2664. varArgTypes = mref.VarargTypes;
  2665. return mref.Member;
  2666. }
  2667. varArgTypes = null;
  2668. Member result = null;
  2669. int codedIndex = mref.Class;
  2670. if (codedIndex == 0) return null;
  2671. TypeNode parent = null;
  2672. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  2673. switch (codedIndex & 0x7)
  2674. {
  2675. case 0x00: parent = this.GetTypeFromDef(codedIndex >> 3); break;
  2676. case 0x01: parent = this.GetTypeFromRef(codedIndex >> 3); break;
  2677. case 0x02: parent = this.GetTypeGlobalMemberContainerTypeFromModule(codedIndex >> 3); break;
  2678. case 0x03: result = this.GetMethodFromDef(codedIndex >> 3);
  2679. if ((((Method)result).CallingConvention & CallingConventionFlags.VarArg) != 0)
  2680. {
  2681. MemoryCursor sRdr = this.tables.GetBlobCursor(mref.Signature);
  2682. sRdr.ReadByte(); //hdr
  2683. int pCount = sRdr.ReadCompressedInt();
  2684. this.ParseTypeSignature(sRdr); //rType
  2685. bool genParameterEncountered = false;
  2686. this.ParseParameterTypes(out varArgTypes, sRdr, pCount, ref genParameterEncountered);
  2687. }
  2688. goto done;
  2689. case 0x04: parent = this.GetTypeFromSpec(codedIndex >> 3); break;
  2690. default: throw new InvalidMetadataException("");
  2691. }
  2692. if (parent != null && parent.IsGeneric)
  2693. {
  2694. if (parent.Template != null)
  2695. this.currentTypeParameters = parent.ConsolidatedTemplateArguments;
  2696. else
  2697. this.currentTypeParameters = parent.ConsolidatedTemplateParameters;
  2698. }
  2699. Identifier memberName = this.tables.GetIdentifier(mref.Name);
  2700. MemoryCursor sigReader = this.tables.GetBlobCursor(mref.Signature);
  2701. byte header = sigReader.ReadByte();
  2702. if (header == 0x6)
  2703. {
  2704. TypeNode fieldType = this.ParseTypeSignature(sigReader);
  2705. TypeNode fType = TypeNode.StripModifiers(fieldType);
  2706. TypeNode parnt = parent;
  2707. while (parnt != null)
  2708. {
  2709. MemberList members = parnt.GetMembersNamed(memberName);
  2710. for (int j = 0, n = members.Count; j < n; j++)
  2711. {
  2712. Field f = members[j] as Field;
  2713. if (f == null) continue;
  2714. if (TypeNode.StripModifiers(f.Type) == fType) { result = f; goto done; }
  2715. }
  2716. Class c = parnt as Class;
  2717. if (c != null) parnt = c.BaseClass; else break;
  2718. }
  2719. if (result == null)
  2720. {
  2721. result = new Field(memberName);
  2722. result.DeclaringType = parent;
  2723. ((Field)result).Type = fieldType;
  2724. goto error;
  2725. }
  2726. goto done;
  2727. }
  2728. int typeParamCount = int.MinValue;
  2729. CallingConventionFlags callingConvention = CallingConventionFlags.Default;
  2730. if ((header & 0x20) != 0) callingConvention |= CallingConventionFlags.HasThis;
  2731. if ((header & 0x40) != 0) callingConvention |= CallingConventionFlags.ExplicitThis;
  2732. switch (header & 7)
  2733. {
  2734. case 1: callingConvention |= CallingConventionFlags.C; break;
  2735. case 2: callingConvention |= CallingConventionFlags.StandardCall; break;
  2736. case 3: callingConvention |= CallingConventionFlags.ThisCall; break;
  2737. case 4: callingConvention |= CallingConventionFlags.FastCall; break;
  2738. case 5: callingConvention |= CallingConventionFlags.VarArg; break;
  2739. }
  2740. if ((header & 0x10) != 0)
  2741. {
  2742. typeParamCount = sigReader.ReadCompressedInt();
  2743. callingConvention |= CallingConventionFlags.Generic;
  2744. }
  2745. int paramCount = sigReader.ReadCompressedInt();
  2746. TypeNodeList savedMethodTypeParameters = this.currentMethodTypeParameters;
  2747. this.currentTypeParameters = parent.ConsolidatedTemplateArguments;
  2748. TypeNode pnt = parent;
  2749. if (numGenericArgs > 0)
  2750. {
  2751. while (pnt != null)
  2752. {
  2753. MemberList members = pnt.GetMembersNamed(memberName);
  2754. for (int k = 0, n = members.Count; k < n; k++)
  2755. {
  2756. Method m = members[k] as Method;
  2757. if (m == null) continue;
  2758. if (m.TemplateParameters == null || m.TemplateParameters.Count != numGenericArgs) continue;
  2759. if (m.Parameters == null || m.Parameters.Count != paramCount) continue;
  2760. this.currentMethodTypeParameters = m.TemplateParameters;
  2761. this.currentTypeParameters = pnt.ConsolidatedTemplateArguments;
  2762. goto parseSignature;
  2763. }
  2764. Class c = pnt as Class;
  2765. if (c != null) pnt = c.BaseClass; else break;
  2766. }
  2767. }
  2768. parseSignature:
  2769. TypeNode returnType = this.ParseTypeSignature(sigReader);
  2770. if (returnType == null) returnType = CoreSystemTypes.Object;
  2771. bool genericParameterEncountered = returnType.IsGeneric;
  2772. TypeNodeList paramTypes = this.ParseParameterTypes(out varArgTypes, sigReader, paramCount, ref genericParameterEncountered);
  2773. this.currentMethodTypeParameters = savedMethodTypeParameters;
  2774. this.currentTypeParameters = savedCurrentTypeParameters;
  2775. pnt = parent;
  2776. while (pnt != null)
  2777. {
  2778. MemberList members = pnt.GetMembersNamed(memberName);
  2779. for (int k = 0, n = members.Count; k < n; k++)
  2780. {
  2781. Method m = members[k] as Method;
  2782. if (m == null) continue;
  2783. if (m.ReturnType == null) continue;
  2784. TypeNode mrtype = TypeNode.StripModifiers(m.ReturnType);
  2785. //^ assert mrtype != null;
  2786. if (!mrtype.IsStructurallyEquivalentTo(TypeNode.StripModifiers(returnType))) continue;
  2787. if (!m.ParameterTypesMatchStructurally(paramTypes)) continue;
  2788. if (m.CallingConvention != callingConvention) continue;
  2789. if (typeParamCount != int.MinValue && (!m.IsGeneric || m.TemplateParameters == null || m.TemplateParameters.Count != typeParamCount))
  2790. continue;
  2791. result = m;
  2792. goto done;
  2793. }
  2794. if (memberName.UniqueIdKey == StandardIds.Ctor.UniqueIdKey)
  2795. {
  2796. //Can't run up the base class chain for constructors.
  2797. members = pnt.GetConstructors();
  2798. if (members != null && members.Count == 1 && paramCount == 0)
  2799. {
  2800. //Only one constructor. The CLR metadata API's seem to think that this should match the empty signature
  2801. result = members[0];
  2802. goto done;
  2803. }
  2804. break;
  2805. }
  2806. Class c = pnt as Class;
  2807. if (c != null) pnt = c.BaseClass; else break;
  2808. }
  2809. if (result == null)
  2810. {
  2811. ParameterList parameters = new ParameterList();
  2812. for (int j = 0; j < paramCount; j++)
  2813. {
  2814. Parameter p = new Parameter(Identifier.Empty, paramTypes[j]);
  2815. parameters.Add(p);
  2816. }
  2817. //TODO: let the caller indicate if it expects a constructor
  2818. Method meth = new Method(parent, null, memberName, parameters, returnType, null);
  2819. meth.CallingConvention = callingConvention;
  2820. if ((callingConvention & CallingConventionFlags.HasThis) == 0) meth.Flags |= MethodFlags.Static;
  2821. result = meth;
  2822. }
  2823. error:
  2824. if (this.module != null)
  2825. {
  2826. HandleError(this.module, String.Format(CultureInfo.CurrentCulture,
  2827. ExceptionStrings.CouldNotResolveMemberReference, parent.FullName + "::" + memberName));
  2828. if (parent != null) parent.Members.Add(result);
  2829. }
  2830. done:
  2831. if (Reader.CanCacheMember(result))
  2832. {
  2833. this.tables.MemberRefTable[i - 1].Member = result;
  2834. this.tables.MemberRefTable[i - 1].VarargTypes = varArgTypes;
  2835. }
  2836. this.currentTypeParameters = savedCurrentTypeParameters;
  2837. return result;
  2838. }
  2839. private static bool CanCacheMethodHelper(Method/*!*/ method)
  2840. {
  2841. if (method.IsGeneric)
  2842. {
  2843. if (method.TemplateArguments == null)
  2844. return false;
  2845. for (int i = 0; i < method.TemplateArguments.Count; i++)
  2846. if (!CanCacheTypeNode(method.TemplateArguments[i]))
  2847. return false;
  2848. }
  2849. return true;
  2850. }
  2851. private static bool CanCacheMember(Member/*!*/ member)
  2852. {
  2853. return (member.DeclaringType == null || CanCacheTypeNode(member.DeclaringType)) &&
  2854. (member.NodeType != NodeType.Method || CanCacheMethodHelper((Method)member));
  2855. }
  2856. private TypeNodeList/*!*/ ParseParameterTypes(out TypeNodeList varArgTypes, MemoryCursor/*!*/ sigReader,
  2857. int paramCount, ref bool genericParameterEncountered)
  2858. {
  2859. varArgTypes = null;
  2860. TypeNodeList paramTypes = new TypeNodeList();
  2861. for(int j = 0; j < paramCount; j++)
  2862. {
  2863. TypeNode paramType = this.ParseTypeSignature(sigReader);
  2864. if(paramType == null)
  2865. {
  2866. // Got a sentinel
  2867. varArgTypes = new TypeNodeList();
  2868. j--;
  2869. continue;
  2870. }
  2871. if(varArgTypes != null)
  2872. {
  2873. varArgTypes.Add(paramType);
  2874. continue;
  2875. }
  2876. if(paramType.IsGeneric)
  2877. genericParameterEncountered = true;
  2878. paramTypes.Add(paramType);
  2879. }
  2880. return paramTypes;
  2881. }
  2882. private bool TypeDefIsClass(int i)
  2883. {
  2884. if (i == 0) return false;
  2885. TypeDefRow typeDef = this.tables.TypeDefTable[i - 1];
  2886. if (typeDef.Type != null) return typeDef.Type is Class;
  2887. if ((typeDef.Flags & (int)TypeFlags.Interface) != 0) return false;
  2888. return this.TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(typeDef.Extends);
  2889. }
  2890. private bool TypeDefIsClassButNotValueTypeBaseClass(int i)
  2891. {
  2892. if (i == 0) return false;
  2893. TypeDefRow typeDef = this.tables.TypeDefTable[i - 1];
  2894. if (typeDef.Type != null) return typeDef.Type != CoreSystemTypes.ValueType && typeDef.Type != CoreSystemTypes.Enum && typeDef.Type is Class;
  2895. if ((typeDef.Flags & (int)TypeFlags.Interface) != 0) return false;
  2896. return this.TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(typeDef.Extends);
  2897. }
  2898. internal TypeNodeList GetInstantiatedTypes()
  2899. {
  2900. TypeNodeList result = null;
  2901. TypeDefRow[] typeDefs = this.tables.TypeDefTable;
  2902. for (int i = 0, n = typeDefs.Length; i < n; i++)
  2903. {
  2904. TypeNode t = typeDefs[i].Type;
  2905. if (t == null) continue;
  2906. if (result == null) result = new TypeNodeList();
  2907. result.Add(t);
  2908. }
  2909. return result;
  2910. }
  2911. internal TypeNode/*!*/ GetTypeFromDef(int i)
  2912. {
  2913. TypeDefRow typeDef = this.tables.TypeDefTable[i - 1];
  2914. if (typeDef.Type != null) return typeDef.Type;
  2915. // Save current state because the helper might change it but this method must not.
  2916. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  2917. TypeNode savedCurrentType = this.currentType;
  2918. try
  2919. {
  2920. return this.GetTypeFromDefHelper(i);
  2921. }
  2922. catch (Exception e)
  2923. {
  2924. if (this.module == null) return new Class();
  2925. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  2926. this.module.MetadataImportErrors.Add(e);
  2927. return new Class();
  2928. }
  2929. finally
  2930. {
  2931. this.currentTypeParameters = savedCurrentTypeParameters;
  2932. this.currentType = savedCurrentType;
  2933. }
  2934. }
  2935. internal TypeNode/*!*/ GetTypeFromDefHelper(int i)
  2936. {
  2937. // This is added to prevent loops.
  2938. // Check the code in GetTypeFromDef which checks != null before callig this function
  2939. this.tables.TypeDefTable[i - 1].Type = Class.Dummy;
  2940. TypeDefRow typeDef = this.tables.TypeDefTable[i - 1];
  2941. Identifier name = this.tables.GetIdentifier(typeDef.Name);
  2942. Identifier namesp = this.tables.GetIdentifier(typeDef.Namespace);
  2943. int firstInterfaceIndex;
  2944. int lastInterfaceIndex;
  2945. this.GetInterfaceIndices(i, out firstInterfaceIndex, out lastInterfaceIndex);
  2946. InterfaceList interfaces = new InterfaceList();
  2947. TypeNode result = this.ConstructCorrectTypeNodeSubclass(i, namesp, firstInterfaceIndex, lastInterfaceIndex,
  2948. (TypeFlags)typeDef.Flags, interfaces, typeDef.Extends,
  2949. name.UniqueIdKey == StandardIds.Enum.UniqueIdKey && namesp.UniqueIdKey == StandardIds.System.UniqueIdKey);
  2950. result.DeclaringModule = this.module;
  2951. result.Name = name;
  2952. result.Namespace = namesp;
  2953. TypeNodeList typeParameters = this.currentTypeParameters = this.GetTypeParametersFor((i << 1) | 0, result);
  2954. result.TemplateParameters = typeParameters;
  2955. result.IsGeneric = typeParameters != null;
  2956. this.tables.TypeDefTable[i - 1].Type = result;
  2957. this.currentType = result;
  2958. this.RemoveTypeParametersBelongToDeclaringType(i, ref typeParameters, result);
  2959. //Now that the type instance has been allocated, it is safe to get hold of things that could refer to this type.
  2960. if (result is Class && result.BaseType == null)
  2961. {
  2962. TypeNode baseType = this.DecodeAndGetTypeDefOrRefOrSpec(typeDef.Extends);
  2963. ((Class)result).BaseClass = baseType as Class;
  2964. if (baseType != null && !(baseType is Class) && this.module != null)
  2965. {
  2966. HandleError(this.module, ExceptionStrings.InvalidBaseClass);
  2967. }
  2968. }
  2969. if (result.IsGeneric)
  2970. this.GetTypeParameterConstraints((i << 1) | 0, typeParameters);
  2971. if (firstInterfaceIndex >= 0)
  2972. this.GetInterfaces(i, firstInterfaceIndex, interfaces);
  2973. if ((result.Flags & (TypeFlags.ExplicitLayout | TypeFlags.SequentialLayout)) != 0)
  2974. this.GetClassSizeAndPackingSize(i, result);
  2975. return result;
  2976. }
  2977. private void GetInterfaceIndices(int i, out int firstInterfaceIndex, out int lastInterfaceIndex)
  2978. {
  2979. firstInterfaceIndex = -1;
  2980. lastInterfaceIndex = -1;
  2981. InterfaceImplRow[] intfaces = this.tables.InterfaceImplTable;
  2982. //TODO: binary search
  2983. for (int j = 0, n = intfaces.Length; j < n; j++)
  2984. {
  2985. if (intfaces[j].Class != i) continue;
  2986. if (firstInterfaceIndex == -1)
  2987. firstInterfaceIndex = j;
  2988. lastInterfaceIndex = j;
  2989. }
  2990. }
  2991. private void GetClassSizeAndPackingSize(int i, TypeNode/*!*/ result)
  2992. {
  2993. ClassLayoutRow[] classLayouts = tables.ClassLayoutTable;
  2994. for (int j = 0, n = classLayouts.Length; j < n; j++)
  2995. { //TODO: binary search
  2996. ClassLayoutRow clr = classLayouts[j];
  2997. if (clr.Parent == i)
  2998. {
  2999. result.ClassSize = clr.ClassSize;
  3000. result.PackingSize = clr.PackingSize;
  3001. break;
  3002. }
  3003. }
  3004. }
  3005. private void GetInterfaces(int i, int firstInterfaceIndex, InterfaceList/*!*/ interfaces)
  3006. {
  3007. InterfaceImplRow[] intfaces = this.tables.InterfaceImplTable;
  3008. for (int j = firstInterfaceIndex, n = intfaces.Length; j < n; j++)
  3009. {
  3010. if (intfaces[j].Class != i) continue; //TODO: break if sorted
  3011. TypeNode ifaceT = this.DecodeAndGetTypeDefOrRefOrSpec(intfaces[j].Interface);
  3012. Interface iface = ifaceT as Interface;
  3013. if (iface == null)
  3014. {
  3015. iface = new Interface();
  3016. if (ifaceT != null)
  3017. {
  3018. iface.DeclaringModule = ifaceT.DeclaringModule;
  3019. iface.Namespace = ifaceT.Namespace;
  3020. iface.Name = ifaceT.Name;
  3021. }
  3022. }
  3023. interfaces.Add(iface);
  3024. }
  3025. }
  3026. private void RemoveTypeParametersBelongToDeclaringType(int i, ref TypeNodeList typeParameters, TypeNode/*!*/ type)
  3027. {
  3028. NestedClassRow[] nestedClasses = tables.NestedClassTable;
  3029. for(int j = 0, n = nestedClasses.Length; j < n; j++)
  3030. { //TODO: binary search
  3031. NestedClassRow ncr = nestedClasses[j];
  3032. if(ncr.NestedClass == i)
  3033. {
  3034. type.DeclaringType = this.GetTypeFromDef(ncr.EnclosingClass);
  3035. if(type.DeclaringType != null && type.DeclaringType.IsGeneric)
  3036. {
  3037. //remove type parameters that belong to declaring type from nested type's list
  3038. if(type.templateParameters != null)
  3039. {
  3040. int icount = GetInheritedTypeParameterCount(type);
  3041. int rcount = type.templateParameters.Count;
  3042. if(icount >= rcount)
  3043. type.templateParameters = null;
  3044. else
  3045. {
  3046. TypeNodeList tpars = new TypeNodeList();
  3047. for(int k = icount; k < rcount; k++)
  3048. tpars.Add(type.templateParameters[k]);
  3049. type.templateParameters = tpars;
  3050. }
  3051. this.currentTypeParameters = typeParameters = type.ConsolidatedTemplateParameters;
  3052. }
  3053. }
  3054. break;
  3055. }
  3056. }
  3057. }
  3058. private TypeNode/*!*/ ConstructCorrectTypeNodeSubclass(int i, Identifier/*!*/ namesp, int firstInterfaceIndex, int lastInterfaceIndex,
  3059. TypeFlags flags, InterfaceList interfaces, int baseTypeCodedIndex, bool isSystemEnum)
  3060. {
  3061. TypeNode result;
  3062. TypeNode.TypeAttributeProvider attributeProvider = new TypeNode.TypeAttributeProvider(this.GetTypeAttributes);
  3063. TypeNode.NestedTypeProvider nestedTypeProvider = new TypeNode.NestedTypeProvider(this.GetNestedTypes);
  3064. TypeNode.TypeMemberProvider memberProvider = new TypeNode.TypeMemberProvider(this.GetTypeMembers);
  3065. bool isTemplateParameter = false;
  3066. if ((flags & TypeFlags.Interface) != 0)
  3067. {
  3068. if (isTemplateParameter)
  3069. result = new TypeParameter(interfaces, nestedTypeProvider, attributeProvider, memberProvider, i);
  3070. else
  3071. result = new Interface(interfaces, nestedTypeProvider, attributeProvider, memberProvider, i);
  3072. }
  3073. else if (isTemplateParameter)
  3074. {
  3075. result = new ClassParameter(nestedTypeProvider, attributeProvider, memberProvider, i);
  3076. }
  3077. else
  3078. {
  3079. result = null;
  3080. TypeNode baseClass = this.GetTypeIfNotGenericInstance(baseTypeCodedIndex);
  3081. if (baseClass != null)
  3082. {
  3083. if (baseClass == CoreSystemTypes.MulticastDelegate) //TODO: handle single cast delegates
  3084. result = new DelegateNode(nestedTypeProvider, attributeProvider, memberProvider, i);
  3085. else if (baseClass == CoreSystemTypes.Enum)
  3086. result = new EnumNode(nestedTypeProvider, attributeProvider, memberProvider, i);
  3087. else if (baseClass == CoreSystemTypes.ValueType &&
  3088. !(isSystemEnum && (flags & TypeFlags.Sealed) == 0))
  3089. {
  3090. result = new Struct(nestedTypeProvider, attributeProvider, memberProvider, i);
  3091. }
  3092. }
  3093. if(result == null)
  3094. result = new Class(nestedTypeProvider, attributeProvider, memberProvider, i);
  3095. }
  3096. result.Flags = flags;
  3097. result.Interfaces = interfaces;
  3098. return result;
  3099. }
  3100. private TrivialHashtable/*<Ident,TypeExtensionProvider>*//*!*/ TypeExtensionTable = new TrivialHashtable();
  3101. delegate TypeNode TypeExtensionProvider(TypeNode.NestedTypeProvider nprovider, TypeNode.TypeAttributeProvider aprovider, TypeNode.TypeMemberProvider mprovider, TypeNode baseType, object handle);
  3102. private static TypeNode DummyTypeExtensionProvider(TypeNode.NestedTypeProvider nprovider, TypeNode.TypeAttributeProvider aprovider, TypeNode.TypeMemberProvider mprovider, TypeNode baseType, object handle)
  3103. {
  3104. return null;
  3105. }
  3106. private TypeExtensionProvider/*!*/ dummyTEProvider = new TypeExtensionProvider(DummyTypeExtensionProvider);
  3107. private TypeNode GetTypeExtensionFromDef(TypeNode.NestedTypeProvider nestedTypeProvider, TypeNode.TypeAttributeProvider attributeProvider, TypeNode.TypeMemberProvider memberProvider, object handle, TypeNode baseType, Interface/*!*/ lastInterface)
  3108. {
  3109. if (lastInterface.Namespace.UniqueIdKey == StandardIds.CciTypeExtensions.UniqueIdKey)
  3110. {
  3111. TypeExtensionProvider teprovider = (TypeExtensionProvider)TypeExtensionTable[lastInterface.Name.UniqueIdKey];
  3112. if (teprovider == null)
  3113. {
  3114. string loc = lastInterface.DeclaringModule.Location.ToLower(CultureInfo.InvariantCulture);
  3115. if (loc.EndsWith(".runtime.dll"))
  3116. {
  3117. loc = System.IO.Path.GetFileName(loc);
  3118. string compilerDllName = loc.Replace(".runtime.dll", "");
  3119. System.Reflection.Assembly rassem;
  3120. try
  3121. {
  3122. rassem = System.Reflection.Assembly.Load(compilerDllName);
  3123. }
  3124. catch
  3125. {
  3126. HandleError(this.module, string.Format(CultureInfo.CurrentCulture, ExceptionStrings.CannotLoadTypeExtension, lastInterface.FullName, compilerDllName));
  3127. goto ExtensionNotFound;
  3128. }
  3129. if (rassem == null) goto ExtensionNotFound;
  3130. System.Type tprov = rassem.GetType(StandardIds.CciTypeExtensions.Name + "." + lastInterface.Name.Name + "Provider");
  3131. if (tprov == null) goto ExtensionNotFound;
  3132. System.Reflection.MethodInfo providerMethod = tprov.GetMethod("For");
  3133. if (providerMethod == null) goto ExtensionNotFound;
  3134. teprovider = (TypeExtensionProvider)Delegate.CreateDelegate(typeof(TypeExtensionProvider), providerMethod);
  3135. ExtensionNotFound: ;
  3136. if (teprovider == null)
  3137. {
  3138. // install a not-found dummy provider
  3139. teprovider = this.dummyTEProvider;
  3140. }
  3141. TypeExtensionTable[lastInterface.Name.UniqueIdKey] = teprovider;
  3142. }
  3143. }
  3144. if (teprovider == null) return null;
  3145. return teprovider(nestedTypeProvider, attributeProvider, memberProvider, baseType, handle);
  3146. }
  3147. return null;
  3148. }
  3149. private static int GetInheritedTypeParameterCount(TypeNode type)
  3150. {
  3151. if (type == null) return 0;
  3152. int n = 0;
  3153. type = type.DeclaringType;
  3154. while (type != null)
  3155. {
  3156. n += type.templateParameters == null ? 0 : type.templateParameters.Count;
  3157. type = type.DeclaringType;
  3158. }
  3159. return n;
  3160. }
  3161. private TypeNode/*!*/ GetTypeGlobalMemberContainerTypeFromModule(int i)
  3162. {
  3163. ModuleRefRow mr = this.tables.ModuleRefTable[i - 1];
  3164. Module mod = mr.Module;
  3165. TypeNode result = null;
  3166. if(mod != null && mod.Types != null && mod.Types.Count > 0)
  3167. result = mod.Types[0];
  3168. if(result != null)
  3169. return result;
  3170. result = this.GetDummyTypeNode(Identifier.Empty, Identifier.For("<Module>"), mod, null, false);
  3171. if(mod != null)
  3172. mod.Types = new TypeNodeList(new[] { result });
  3173. return result;
  3174. }
  3175. internal void GetNamespaces()
  3176. //^ ensures this.namespaceTable != null;
  3177. {
  3178. TypeDefRow[] typeDefs = this.tables.TypeDefTable;
  3179. int n = typeDefs.Length;
  3180. TrivialHashtable nsT = this.namespaceTable = new TrivialHashtable(n * 2);
  3181. TrivialHashtable nsFor = new TrivialHashtable();
  3182. NamespaceList nsL = this.namespaceList = new NamespaceList();
  3183. for(int i = 0; i < n; i++)
  3184. {
  3185. TypeDefRow typeDef = typeDefs[i];
  3186. TrivialHashtable ns = (TrivialHashtable)nsT[typeDef.NamespaceKey];
  3187. Namespace nSpace = (Namespace)nsFor[typeDef.NamespaceKey];
  3188. if(ns == null)
  3189. {
  3190. nsT[typeDef.NamespaceKey] = ns = new TrivialHashtable();
  3191. nsFor[typeDef.NamespaceKey] = nSpace = new Namespace(typeDef.NamespaceId);
  3192. nsL.Add(nSpace);
  3193. }
  3194. Debug.Assert(nSpace != null);
  3195. if((typeDef.Flags & (int)TypeFlags.VisibilityMask) == 0)
  3196. ns[typeDef.NameKey] = i + 1;
  3197. else
  3198. if((typeDef.Flags & (int)TypeFlags.VisibilityMask) == 1)
  3199. {
  3200. nSpace.isPublic = true;
  3201. ns[typeDef.NameKey] = i + 1;
  3202. }
  3203. }
  3204. }
  3205. private TypeNode GetTypeFromName(Identifier/*!*/ Namespace, Identifier/*!*/ name)
  3206. {
  3207. try
  3208. {
  3209. if (this.namespaceTable == null) this.GetNamespaces();
  3210. //^ assert this.namespaceTable != null;
  3211. TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[Namespace.UniqueIdKey];
  3212. if (nsTable == null) return this.GetForwardedTypeFromName(Namespace, name);
  3213. object ti = nsTable[name.UniqueIdKey];
  3214. if (ti == null) return this.GetForwardedTypeFromName(Namespace, name);
  3215. TypeNode t = this.GetTypeFromDef((int)ti);
  3216. return t;
  3217. }
  3218. catch (Exception e)
  3219. {
  3220. if (this.module == null) return null;
  3221. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  3222. this.module.MetadataImportErrors.Add(e);
  3223. return null;
  3224. }
  3225. }
  3226. private TypeNode GetForwardedTypeFromName(Identifier/*!*/ Namespace, Identifier/*!*/ name)
  3227. {
  3228. ExportedTypeRow[] exportedTypes = this.tables.ExportedTypeTable;
  3229. for (int i = 0, n = exportedTypes == null ? 0 : exportedTypes.Length; i < n; i++)
  3230. {
  3231. ExportedTypeRow etr = exportedTypes[i];
  3232. if ((etr.Flags & (int)TypeFlags.Forwarder) == 0) continue;
  3233. if (this.tables.GetString(etr.TypeNamespace) != Namespace.Name ||
  3234. this.tables.GetString(etr.TypeName) != name.Name) continue;
  3235. int index = etr.Implementation >> 2;
  3236. AssemblyRefRow arr = this.tables.AssemblyRefTable[index - 1];
  3237. return arr.AssemblyReference.Assembly.GetType(Namespace, name);
  3238. }
  3239. return null;
  3240. }
  3241. internal bool IsValidTypeName(Identifier/*!*/ Namespace, Identifier/*!*/ name)
  3242. {
  3243. try
  3244. {
  3245. if (this.namespaceTable == null) this.GetNamespaces();
  3246. //^ assert this.namespaceTable != null;
  3247. TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[Namespace.UniqueIdKey];
  3248. if (nsTable == null) return false;
  3249. return nsTable[name.UniqueIdKey] != null;
  3250. }
  3251. catch (Exception e)
  3252. {
  3253. if (this.module == null) return false;
  3254. if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
  3255. this.module.MetadataImportErrors.Add(e);
  3256. return false;
  3257. }
  3258. }
  3259. internal TypeNode/*!*/ GetTypeFromRef(int i)
  3260. {
  3261. return this.GetTypeFromRef(i, false);
  3262. }
  3263. internal TypeNode/*!*/ GetTypeFromRef(int i, bool expectStruct)
  3264. {
  3265. TypeRefRow[] trtable = this.tables.TypeRefTable;
  3266. TypeRefRow trr = trtable[i - 1];
  3267. TypeNode result = trr.Type;
  3268. if (result != null) return result;
  3269. Identifier name = tables.GetIdentifier(trr.Name);
  3270. Identifier namesp = tables.GetIdentifier(trr.Namespace);
  3271. int resolutionScope = trr.ResolutionScope;
  3272. Module declaringModule = null;
  3273. TypeNode declaringType = null;
  3274. int index = resolutionScope >> 2;
  3275. switch (resolutionScope & 0x3)
  3276. {
  3277. case 0:
  3278. declaringModule = this.module;
  3279. //^ assume declaringModule != null;
  3280. result = declaringModule.GetType(namesp, name);
  3281. //REVIEW: deal with case where ref is in same (multi-module) assembly, but not the current module? index == 0
  3282. break;
  3283. case 1:
  3284. declaringModule = this.tables.ModuleRefTable[index - 1].Module;
  3285. if (declaringModule != null)
  3286. result = declaringModule.GetType(namesp, name);
  3287. break;
  3288. case 2:
  3289. declaringModule = this.tables.AssemblyRefTable[index - 1].AssemblyReference.Assembly;
  3290. if (declaringModule != null)
  3291. result = declaringModule.GetType(namesp, name);
  3292. break;
  3293. case 3:
  3294. declaringType = this.GetTypeFromRef(index);
  3295. declaringModule = declaringType.DeclaringModule;
  3296. if (namesp == null || namesp.length == 0)
  3297. result = (TypeNode)declaringType.GetMembersNamed(name).FirstOrDefault();
  3298. else
  3299. result = (TypeNode)declaringType.GetMembersNamed(Identifier.For(namesp.Name + "." + name.Name)).FirstOrDefault();
  3300. break;
  3301. default:
  3302. declaringModule = this.module;
  3303. break;
  3304. }
  3305. if (result == null)
  3306. result = this.GetDummyTypeNode(namesp, name, declaringModule, declaringType, expectStruct);
  3307. trtable[i - 1].Type = result;
  3308. if (!Reader.CanCacheTypeNode(result))
  3309. trtable[i - 1].Type = null;
  3310. return result;
  3311. }
  3312. private TypeNode/*!*/ GetDummyTypeNode(Identifier namesp, Identifier name, Module declaringModule, TypeNode declaringType, bool expectStruct)
  3313. {
  3314. TypeNode result = null;
  3315. if (this.module != null)
  3316. {
  3317. string modName = declaringModule == null ? "" : declaringModule.Name == null ? "" : declaringModule.Name.ToString();
  3318. HandleError(this.module, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.CouldNotResolveTypeReference,
  3319. "[" + modName + "]" + namesp + "." + name));
  3320. }
  3321. result = expectStruct ? (TypeNode)new Struct() : (TypeNode)new Class();
  3322. if (name != null && name.ToString().StartsWith("I") && name.ToString().Length > 1 && char.IsUpper(name.ToString()[1]))
  3323. result = new Interface();
  3324. result.Flags |= TypeFlags.Public;
  3325. result.Name = name;
  3326. result.Namespace = namesp;
  3327. if (declaringType != null)
  3328. {
  3329. result.DeclaringType = declaringType;
  3330. result.DeclaringModule = declaringType.DeclaringModule;
  3331. declaringType.Members.Add(result);
  3332. }
  3333. else
  3334. {
  3335. if (declaringModule == null) declaringModule = this.module;
  3336. //^ assume declaringModule != null;
  3337. result.DeclaringModule = declaringModule;
  3338. if (declaringModule.types != null)
  3339. declaringModule.types.Add(result);
  3340. }
  3341. return result;
  3342. }
  3343. private bool TypeSpecIsClass(int i)
  3344. {
  3345. TypeSpecRow tsr = this.tables.TypeSpecTable[i - 1];
  3346. if (tsr.Type != null) return tsr.Type is Class;
  3347. this.tables.GetSignatureLength(tsr.Signature);
  3348. return this.TypeSignatureIsClass(this.tables.GetNewCursor());
  3349. }
  3350. internal TypeNode/*!*/ GetTypeFromSpec(int i)
  3351. {
  3352. TypeSpecRow tsr = this.tables.TypeSpecTable[i - 1];
  3353. if (tsr.Type != null) return tsr.Type;
  3354. this.tables.GetSignatureLength(tsr.Signature);
  3355. bool pinned = false;
  3356. bool isTypeArgument = false;
  3357. TypeNode result = this.ParseTypeSignature(this.tables.GetNewCursor(), ref pinned, ref isTypeArgument);
  3358. if (result == null) result = new Class();
  3359. //Get custom attributes
  3360. AttributeList attributes = this.GetCustomAttributesFor((i << 5) | 13);
  3361. if (attributes.Count > 0)
  3362. {
  3363. //Append attributes "inherited" from template to metadata attributes
  3364. AttributeList templAttributes = result.Attributes;
  3365. for (int j = 0, n = templAttributes == null ? 0 : templAttributes.Count; j < n; j++)
  3366. {
  3367. AttributeNode attr = result.Attributes[j];
  3368. if (attr == null) continue;
  3369. attributes.Add(attr);
  3370. }
  3371. result.Attributes = attributes;
  3372. }
  3373. if (!isTypeArgument && Reader.CanCacheTypeNode(result))
  3374. this.tables.TypeSpecTable[i - 1].Type = result;
  3375. return result;
  3376. }
  3377. private static bool CanCacheTypeNode(TypeNode/*!*/ type)
  3378. {
  3379. return !type.IsGeneric && (type.Template == null || !type.IsNotFullySpecialized) &&
  3380. type.NodeType != NodeType.TypeParameter && type.NodeType != NodeType.ClassParameter &&
  3381. type.NodeType != NodeType.InterfaceExpression;
  3382. }
  3383. private static Module GetNestedModule(Module module, string modName, ref string modLocation)
  3384. {
  3385. if (module == null || modName == null) { Debug.Assert(false); return null; }
  3386. Module mod = module.GetNestedModule(modName);
  3387. if (mod == null)
  3388. {
  3389. if (module.Location != null)
  3390. modLocation = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(module.Location), modName);
  3391. if (modLocation != null && System.IO.File.Exists(modLocation))
  3392. {
  3393. mod = Module.GetModule(modLocation);
  3394. if (mod != null)
  3395. {
  3396. mod.ContainingAssembly = module.ContainingAssembly;
  3397. module.ModuleReferences.Add(new ModuleReference(modName, mod));
  3398. }
  3399. }
  3400. }
  3401. if (mod == null)
  3402. {
  3403. HandleError(module, String.Format(CultureInfo.CurrentCulture,
  3404. ExceptionStrings.CouldNotFindReferencedModule, modLocation));
  3405. mod = new Module();
  3406. mod.Name = modName;
  3407. mod.ContainingAssembly = module.ContainingAssembly;
  3408. mod.Kind = ModuleKind.DynamicallyLinkedLibrary;
  3409. }
  3410. return mod;
  3411. }
  3412. private void GetTypeList(Module/*!*/ module)
  3413. {
  3414. TypeNodeList types = new TypeNodeList();
  3415. TypeDefRow[] typeDefs = this.tables.TypeDefTable;
  3416. for (int i = 0, n = typeDefs.Length; i < n; i++)
  3417. {
  3418. TypeNode t = this.GetTypeFromDef(i + 1);
  3419. if (t != null && t.DeclaringType == null) types.Add(t);
  3420. }
  3421. module.Types = types;
  3422. AssemblyNode assem = module as AssemblyNode;
  3423. if (assem == null) return;
  3424. types = new TypeNodeList();
  3425. ExportedTypeRow[] exportedTypes = this.tables.ExportedTypeTable;
  3426. for (int i = 0, n = exportedTypes.Length; i < n; i++)
  3427. {
  3428. ExportedTypeRow etr = exportedTypes[i];
  3429. Identifier nameSpace = Identifier.For(this.tables.GetString(etr.TypeNamespace));
  3430. Identifier typeName = Identifier.For(this.tables.GetString(etr.TypeName));
  3431. TypeNode exportedType = null;
  3432. switch (etr.Implementation & 0x3)
  3433. {
  3434. case 0:
  3435. string modName = this.tables.GetString(this.tables.FileTable[(etr.Implementation >> 2) - 1].Name);
  3436. string modLocation = modName;
  3437. Module mod = GetNestedModule(assem, modName, ref modLocation);
  3438. if (mod == null) { Debug.Assert(false); break; }
  3439. exportedType = mod.GetType(nameSpace, typeName);
  3440. if (exportedType == null)
  3441. {
  3442. HandleError(assem, String.Format(CultureInfo.CurrentCulture,
  3443. ExceptionStrings.CouldNotFindExportedTypeInModule, nameSpace + "." + typeName, modLocation));
  3444. exportedType = new Class();
  3445. exportedType.Name = typeName;
  3446. exportedType.Namespace = nameSpace;
  3447. exportedType.Flags = TypeFlags.Class | TypeFlags.Public;
  3448. exportedType.DeclaringModule = mod;
  3449. }
  3450. break;
  3451. case 1:
  3452. AssemblyReference aref = this.tables.AssemblyRefTable[(etr.Implementation >> 2) - 1].AssemblyReference;
  3453. if (aref == null)
  3454. {
  3455. HandleError(assem, ExceptionStrings.BadMetadataInExportTypeTableNoSuchAssemblyReference);
  3456. aref = new AssemblyReference("dummy assembly for bad reference");
  3457. }
  3458. AssemblyNode a = aref.Assembly;
  3459. if (a == null) { Debug.Assert(false); continue; }
  3460. exportedType = a.GetType(nameSpace, typeName);
  3461. if (exportedType == null)
  3462. {
  3463. HandleError(assem, String.Format(CultureInfo.CurrentCulture,
  3464. ExceptionStrings.CouldNotFindExportedTypeInAssembly, nameSpace + "." + typeName, a.StrongName));
  3465. exportedType = new Class();
  3466. exportedType.Name = typeName;
  3467. exportedType.Namespace = nameSpace;
  3468. exportedType.Flags = TypeFlags.Class | TypeFlags.Public;
  3469. exportedType.DeclaringModule = a;
  3470. }
  3471. break;
  3472. case 2:
  3473. TypeNode parentType = types[(etr.Implementation >> 2) - 1];
  3474. if (parentType == null)
  3475. {
  3476. HandleError(assem, ExceptionStrings.BadMetadataInExportTypeTableNoSuchParentType);
  3477. parentType = new Class();
  3478. parentType.DeclaringModule = this.module;
  3479. parentType.Name = Identifier.For("Missing parent type");
  3480. }
  3481. exportedType = parentType.GetNestedType(typeName);
  3482. if (exportedType == null)
  3483. {
  3484. HandleError(assem, String.Format(CultureInfo.CurrentCulture,
  3485. ExceptionStrings.CouldNotFindExportedNestedTypeInType, typeName, parentType.FullName));
  3486. exportedType = new Class();
  3487. exportedType.Name = typeName;
  3488. exportedType.Flags = TypeFlags.Class | TypeFlags.NestedPublic;
  3489. exportedType.DeclaringType = parentType;
  3490. exportedType.DeclaringModule = parentType.DeclaringModule;
  3491. }
  3492. break;
  3493. }
  3494. types.Add(exportedType);
  3495. }
  3496. assem.ExportedTypes = types;
  3497. }
  3498. private void GetNestedTypes(TypeNode/*!*/ type, object/*!*/ handle)
  3499. {
  3500. type.nestedTypes = null;
  3501. TypeNodeList result = new TypeNodeList();
  3502. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  3503. try
  3504. {
  3505. if(type.IsGeneric)
  3506. {
  3507. if(type.templateParameters == null)
  3508. type.templateParameters = new TypeNodeList();
  3509. this.currentTypeParameters = type.ConsolidatedTemplateParameters;
  3510. }
  3511. this.currentType = type;
  3512. TypeNode declaringType = type.DeclaringType;
  3513. while(this.currentTypeParameters == null && declaringType != null)
  3514. {
  3515. if(declaringType.IsGeneric)
  3516. {
  3517. if(declaringType.templateParameters == null)
  3518. declaringType.templateParameters = new TypeNodeList();
  3519. this.currentTypeParameters = declaringType.ConsolidatedTemplateParameters;
  3520. }
  3521. declaringType = declaringType.DeclaringType;
  3522. }
  3523. MetadataReader tables = this.tables;
  3524. int typeTableIndex = (int)handle;
  3525. TypeDefRow[] typeDefs = tables.TypeDefTable;
  3526. int n = typeDefs.Length;
  3527. if(typeTableIndex < 1 || typeTableIndex > n)
  3528. throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  3529. NestedClassRow[] nestedClasses = tables.NestedClassTable;
  3530. n = nestedClasses.Length;
  3531. for (int i = 0; i < n; i++)
  3532. { //TODO: binary lookup
  3533. NestedClassRow ncr = nestedClasses[i];
  3534. if(ncr.EnclosingClass != typeTableIndex)
  3535. continue;
  3536. TypeNode t = this.GetTypeFromDef(ncr.NestedClass);
  3537. if(t != null)
  3538. {
  3539. if(type.nestedTypes != null)
  3540. return; //A recursive call to GetNestedTypes has already done the deed
  3541. t.DeclaringType = type;
  3542. if((t.Flags & TypeFlags.RTSpecialName) == 0 || t.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)
  3543. result.Add(t);
  3544. }
  3545. else
  3546. {
  3547. throw new InvalidMetadataException("Invalid nested class row");
  3548. }
  3549. }
  3550. type.nestedTypes = result;
  3551. }
  3552. catch(Exception e)
  3553. {
  3554. if(this.module != null)
  3555. {
  3556. if(this.module.MetadataImportErrors == null)
  3557. this.module.MetadataImportErrors = new ArrayList();
  3558. this.module.MetadataImportErrors.Add(e);
  3559. }
  3560. this.currentTypeParameters = savedCurrentTypeParameters;
  3561. }
  3562. }
  3563. private void GetTypeMembers(TypeNode/*!*/ type, object/*!*/ handle)
  3564. {
  3565. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  3566. try
  3567. {
  3568. MetadataReader tables = this.tables;
  3569. int typeTableIndex = (int)handle;
  3570. TypeDefRow[] typeDefs = tables.TypeDefTable;
  3571. FieldRow[] fieldDefs = tables.FieldTable;
  3572. FieldPtrRow[] fieldPtrs = tables.FieldPtrTable;
  3573. MethodRow[] methodDefs = tables.MethodTable;
  3574. MethodPtrRow[] methodPtrs = tables.MethodPtrTable;
  3575. EventMapRow[] eventMaps = tables.EventMapTable;
  3576. EventRow[] eventDefs = tables.EventTable;
  3577. EventPtrRow[] eventPtrs = tables.EventPtrTable;
  3578. MethodImplRow[] methodImpls = tables.MethodImplTable;
  3579. PropertyMapRow[] propertyMaps = tables.PropertyMapTable;
  3580. PropertyPtrRow[] propertyPtrs = tables.PropertyPtrTable;
  3581. PropertyRow[] propertyDefs = this.tables.PropertyTable;
  3582. NestedClassRow[] nestedClasses = tables.NestedClassTable;
  3583. int n = typeDefs.Length;
  3584. if(typeTableIndex < 1 || typeTableIndex > n)
  3585. throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  3586. TypeDefRow td = typeDefs[typeTableIndex - 1];
  3587. if(type != td.Type)
  3588. throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  3589. //Get type members
  3590. if(type.IsGeneric)
  3591. {
  3592. if(type.templateParameters == null)
  3593. type.templateParameters = new TypeNodeList();
  3594. this.currentTypeParameters = type.ConsolidatedTemplateParameters;
  3595. }
  3596. this.currentType = type;
  3597. TypeNode declaringType = type.DeclaringType;
  3598. while(this.currentTypeParameters == null && declaringType != null)
  3599. {
  3600. if(declaringType.IsGeneric)
  3601. {
  3602. if(declaringType.templateParameters == null)
  3603. declaringType.templateParameters = new TypeNodeList();
  3604. this.currentTypeParameters = declaringType.ConsolidatedTemplateParameters;
  3605. }
  3606. declaringType = declaringType.DeclaringType;
  3607. }
  3608. type.members = new MemberList();
  3609. n = nestedClasses.Length;
  3610. for(int i = 0; i < n; i++)
  3611. {
  3612. NestedClassRow ncr = nestedClasses[i];
  3613. if(ncr.EnclosingClass != typeTableIndex)
  3614. continue;
  3615. TypeNode t = this.GetTypeFromDef(ncr.NestedClass);
  3616. if(t != null)
  3617. {
  3618. t.DeclaringType = type;
  3619. if((t.Flags & TypeFlags.RTSpecialName) == 0 || t.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)
  3620. type.Members.Add(t);
  3621. }
  3622. }
  3623. n = typeDefs.Length;
  3624. int m = fieldDefs.Length;
  3625. int start = td.FieldList;
  3626. int end = m + 1; if (typeTableIndex < n) end = typeDefs[typeTableIndex].FieldList;
  3627. if(type is EnumNode)
  3628. this.GetUnderlyingTypeOfEnumNode((EnumNode)type, fieldDefs, fieldPtrs, start, end);
  3629. this.AddFieldsToType(type, fieldDefs, fieldPtrs, start, end);
  3630. m = methodDefs.Length;
  3631. start = td.MethodList;
  3632. end = m + 1; if (typeTableIndex < n) end = typeDefs[typeTableIndex].MethodList;
  3633. this.AddMethodsToType(type, methodPtrs, start, end);
  3634. n = propertyMaps.Length;
  3635. m = propertyDefs.Length;
  3636. for(int i = 0; i < n; i++)
  3637. { //TODO: binary search
  3638. PropertyMapRow pm = propertyMaps[i];
  3639. if(pm.Parent != typeTableIndex)
  3640. continue;
  3641. start = pm.PropertyList;
  3642. end = m + 1; if (i < n - 1) end = propertyMaps[i + 1].PropertyList;
  3643. this.AddPropertiesToType(type, propertyDefs, propertyPtrs, start, end);
  3644. }
  3645. n = eventMaps.Length;
  3646. m = eventDefs.Length;
  3647. for(int i = 0; i < n; i++)
  3648. { //TODO: binary search
  3649. EventMapRow em = eventMaps[i];
  3650. if(em.Parent != typeTableIndex)
  3651. continue;
  3652. start = em.EventList;
  3653. end = m + 1; if (i < n - 1) end = eventMaps[i + 1].EventList;
  3654. this.AddEventsToType(type, eventDefs, eventPtrs, start, end);
  3655. }
  3656. n = methodImpls.Length;
  3657. for(int i = 0; i < n; i++)
  3658. { //TODO: binary search
  3659. MethodImplRow mir = methodImpls[i];
  3660. if(mir.Class != typeTableIndex)
  3661. continue;
  3662. Method implementer = this.GetMethodDefOrRef(mir.MethodBody);
  3663. if(implementer == null)
  3664. continue;
  3665. MethodList implementedInterfaceMethods = implementer.ImplementedInterfaceMethods;
  3666. if(implementedInterfaceMethods == null)
  3667. implementedInterfaceMethods = implementer.ImplementedInterfaceMethods = new MethodList();
  3668. TypeNodeList savedMethodTypeParameters = this.currentMethodTypeParameters;
  3669. this.currentMethodTypeParameters = implementer.TemplateParameters;
  3670. implementedInterfaceMethods.Add(this.GetMethodDefOrRef(mir.MethodDeclaration));
  3671. this.currentMethodTypeParameters = savedMethodTypeParameters;
  3672. }
  3673. this.currentTypeParameters = savedCurrentTypeParameters;
  3674. }
  3675. catch(Exception e)
  3676. {
  3677. if(this.module != null)
  3678. {
  3679. if(this.module.MetadataImportErrors == null)
  3680. this.module.MetadataImportErrors = new ArrayList();
  3681. this.module.MetadataImportErrors.Add(e);
  3682. }
  3683. type.Members = new MemberList();
  3684. this.currentTypeParameters = savedCurrentTypeParameters;
  3685. }
  3686. }
  3687. private void GetTypeAttributes(TypeNode/*!*/ type, object/*!*/ handle)
  3688. {
  3689. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  3690. try
  3691. {
  3692. MetadataReader tables = this.tables;
  3693. int typeTableIndex = (int)handle;
  3694. TypeDefRow[] typeDefs = tables.TypeDefTable;
  3695. int n = typeDefs.Length;
  3696. if (typeTableIndex < 1 || typeTableIndex > n)
  3697. throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  3698. TypeDefRow td = typeDefs[typeTableIndex - 1];
  3699. if (type != td.Type) throw new System.ArgumentOutOfRangeException("handle", ExceptionStrings.InvalidTypeTableIndex);
  3700. //Get custom attributes
  3701. type.Attributes = this.GetCustomAttributesFor((typeTableIndex << 5) | 3);
  3702. this.currentTypeParameters = savedCurrentTypeParameters;
  3703. //Get security attributes
  3704. if ((type.Flags & TypeFlags.HasSecurity) != 0)
  3705. type.SecurityAttributes = this.GetSecurityAttributesFor((typeTableIndex << 2) | 0);
  3706. }
  3707. catch(Exception e)
  3708. {
  3709. if(this.module != null)
  3710. {
  3711. if(this.module.MetadataImportErrors == null)
  3712. this.module.MetadataImportErrors = new ArrayList();
  3713. this.module.MetadataImportErrors.Add(e);
  3714. }
  3715. type.Attributes = new AttributeList();
  3716. this.currentTypeParameters = savedCurrentTypeParameters;
  3717. }
  3718. }
  3719. private TypeNodeList/*!*/ ParseTypeList(MemoryCursor/*!*/ sigReader)
  3720. {
  3721. int n = sigReader.ReadCompressedInt();
  3722. TypeNodeList result = new TypeNodeList();
  3723. for(int i = 0; i < n; i++)
  3724. {
  3725. TypeNode t = this.ParseTypeSignature(sigReader);
  3726. if(t == null || t == Struct.Dummy)
  3727. {
  3728. // Can happen when dealing with a primitive type that implements an interface that references the primitive type.
  3729. // For example, System.String implements IComparable<System.String>.
  3730. if(this.currentType != null && !CoreSystemTypes.Initialized)
  3731. t = this.currentType;
  3732. else
  3733. {
  3734. Debug.Assert(false);
  3735. t = new TypeParameter();
  3736. t.Name = Identifier.For("Bad type parameter in position " + i);
  3737. t.DeclaringModule = this.module;
  3738. }
  3739. }
  3740. result.Add(t);
  3741. }
  3742. return result;
  3743. }
  3744. private bool TypeSignatureIsClass(MemoryCursor/*!*/ sigReader)
  3745. {
  3746. ElementType tok = (ElementType)sigReader.ReadCompressedInt();
  3747. switch (tok)
  3748. {
  3749. case ElementType.Pinned:
  3750. case ElementType.Pointer:
  3751. case ElementType.Reference:
  3752. return this.TypeSignatureIsClass(sigReader);
  3753. case ElementType.OptionalModifier:
  3754. case ElementType.RequiredModifier:
  3755. sigReader.ReadCompressedInt();
  3756. return this.TypeSignatureIsClass(sigReader);
  3757. case ElementType.Class:
  3758. return true;
  3759. case ElementType.GenericTypeInstance:
  3760. return this.TypeSignatureIsClass(sigReader);
  3761. case ElementType.TypeParameter:
  3762. {
  3763. int pnum = sigReader.ReadCompressedInt();
  3764. if (this.currentTypeParameters != null && this.currentTypeParameters.Count > pnum)
  3765. {
  3766. TypeNode tPar = this.currentTypeParameters[pnum];
  3767. return tPar != null && tPar is Class;
  3768. }
  3769. return false;
  3770. }
  3771. case ElementType.MethodParameter:
  3772. {
  3773. int pnum = sigReader.ReadCompressedInt();
  3774. if (this.currentMethodTypeParameters != null && this.currentMethodTypeParameters.Count > pnum)
  3775. {
  3776. TypeNode tPar = this.currentMethodTypeParameters[pnum];
  3777. return tPar != null && tPar is Class;
  3778. }
  3779. return false;
  3780. }
  3781. default:
  3782. return false;
  3783. }
  3784. }
  3785. private TypeNode ParseTypeSignature(MemoryCursor/*!*/ sigReader)
  3786. {
  3787. bool junk = false;
  3788. return this.ParseTypeSignature(sigReader, ref junk, ref junk);
  3789. }
  3790. private TypeNode ParseTypeSignature(MemoryCursor/*!*/ sigReader, ref bool pinned)
  3791. {
  3792. bool junk = false;
  3793. return this.ParseTypeSignature(sigReader, ref pinned, ref junk);
  3794. }
  3795. private TypeNode ParseTypeSignature(MemoryCursor/*!*/ sigReader, ref bool pinned, ref bool isTypeArgument)
  3796. {
  3797. TypeNode elementType;
  3798. ElementType tok = (ElementType)sigReader.ReadCompressedInt();
  3799. if (tok == ElementType.Pinned)
  3800. {
  3801. pinned = true;
  3802. tok = (ElementType)sigReader.ReadCompressedInt();
  3803. }
  3804. switch (tok)
  3805. {
  3806. case ElementType.Boolean: return CoreSystemTypes.Boolean;
  3807. case ElementType.Char: return CoreSystemTypes.Char;
  3808. case ElementType.Double: return CoreSystemTypes.Double;
  3809. case ElementType.Int16: return CoreSystemTypes.Int16;
  3810. case ElementType.Int32: return CoreSystemTypes.Int32;
  3811. case ElementType.Int64: return CoreSystemTypes.Int64;
  3812. case ElementType.Int8: return CoreSystemTypes.Int8;
  3813. case ElementType.IntPtr: return CoreSystemTypes.IntPtr;
  3814. case ElementType.BoxedEnum:
  3815. case ElementType.Object: return CoreSystemTypes.Object;
  3816. case ElementType.Single: return CoreSystemTypes.Single;
  3817. case ElementType.String: return CoreSystemTypes.String;
  3818. case ElementType.DynamicallyTypedReference: return CoreSystemTypes.DynamicallyTypedReference;
  3819. case ElementType.UInt16: return CoreSystemTypes.UInt16;
  3820. case ElementType.UInt32: return CoreSystemTypes.UInt32;
  3821. case ElementType.UInt64: return CoreSystemTypes.UInt64;
  3822. case ElementType.UInt8: return CoreSystemTypes.UInt8;
  3823. case ElementType.UIntPtr: return CoreSystemTypes.UIntPtr;
  3824. case ElementType.Void: return CoreSystemTypes.Void;
  3825. case ElementType.Pointer:
  3826. elementType = this.ParseTypeSignature(sigReader, ref pinned);
  3827. if (elementType == null) elementType = CoreSystemTypes.Object;
  3828. if (elementType == null) return null;
  3829. return elementType.GetPointerType();
  3830. case ElementType.Reference:
  3831. elementType = this.ParseTypeSignature(sigReader, ref pinned);
  3832. if (elementType == null) elementType = CoreSystemTypes.Object;
  3833. return elementType.GetReferenceType();
  3834. case ElementType.FunctionPointer:
  3835. return this.ParseFunctionPointer(sigReader);
  3836. case ElementType.OptionalModifier:
  3837. case ElementType.RequiredModifier:
  3838. TypeNode modifier = this.DecodeAndGetTypeDefOrRefOrSpec(sigReader.ReadCompressedInt());
  3839. if (modifier == null) modifier = CoreSystemTypes.Object;
  3840. TypeNode modified = this.ParseTypeSignature(sigReader, ref pinned);
  3841. if (modified == null) modified = CoreSystemTypes.Object;
  3842. if (modified == null || modified == null) return null;
  3843. if (tok == ElementType.RequiredModifier)
  3844. return RequiredModifier.For(modifier, modified);
  3845. else
  3846. return OptionalModifier.For(modifier, modified);
  3847. case ElementType.Class:
  3848. return this.DecodeAndGetTypeDefOrRefOrSpec(sigReader.ReadCompressedInt());
  3849. case ElementType.ValueType:
  3850. return this.DecodeAndGetTypeDefOrRefOrSpec(sigReader.ReadCompressedInt(), true);
  3851. case ElementType.TypeParameter:
  3852. TypeNode tPar = null;
  3853. int pnum = sigReader.ReadCompressedInt();
  3854. if (this.currentTypeParameters != null && this.currentTypeParameters.Count > pnum)
  3855. tPar = this.currentTypeParameters[pnum];
  3856. if (tPar == null)
  3857. {
  3858. HandleError(this.module, String.Format(CultureInfo.CurrentCulture,
  3859. ExceptionStrings.BadTypeParameterInPositionForType, pnum, this.currentType == null ? "" : this.currentType.FullName));
  3860. tPar = new TypeParameter();
  3861. tPar.Name = Identifier.For("Bad type parameter in position " + pnum);
  3862. tPar.DeclaringModule = this.module;
  3863. }
  3864. isTypeArgument = true;
  3865. return tPar;
  3866. case ElementType.MethodParameter:
  3867. TypeNode mTPar = null;
  3868. pnum = sigReader.ReadCompressedInt();
  3869. if (this.currentMethodTypeParameters != null && this.currentMethodTypeParameters.Count > pnum)
  3870. mTPar = this.currentMethodTypeParameters[pnum];
  3871. if (mTPar == null)
  3872. {
  3873. HandleError(this.module, String.Format(CultureInfo.CurrentCulture,
  3874. ExceptionStrings.BadMethodTypeParameterInPosition, pnum));
  3875. mTPar = new MethodTypeParameter();
  3876. mTPar.Name = Identifier.For("Bad method type parameter in position " + pnum);
  3877. }
  3878. isTypeArgument = true;
  3879. return mTPar;
  3880. case ElementType.GenericTypeInstance:
  3881. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  3882. TypeNode template = this.ParseTypeSignature(sigReader, ref pinned);
  3883. this.currentTypeParameters = savedCurrentTypeParameters;
  3884. if (template == null || template.ConsolidatedTemplateParameters == null) return template; //Likely a dummy type
  3885. if (CoreSystemTypes.Initialized)
  3886. {
  3887. if (this.currentTypeParameters == null || this.currentTypeParameters.Count == 0)
  3888. this.currentTypeParameters = template.ConsolidatedTemplateParameters;
  3889. TypeNodeList genArgs = this.ParseTypeList(sigReader);
  3890. if (this.module == null) return null;
  3891. TypeNode genInst = template.GetGenericTemplateInstance(this.module, genArgs);
  3892. this.currentTypeParameters = savedCurrentTypeParameters;
  3893. return genInst;
  3894. }
  3895. InterfaceExpression ifaceExpr = new InterfaceExpression(null);
  3896. ifaceExpr.Template = template;
  3897. ifaceExpr.Namespace = template.Namespace;
  3898. ifaceExpr.Name = template.Name;
  3899. ifaceExpr.TemplateArguments = this.ParseTypeList(sigReader);
  3900. this.currentTypeParameters = savedCurrentTypeParameters;
  3901. return ifaceExpr;
  3902. case ElementType.SzArray:
  3903. elementType = this.ParseTypeSignature(sigReader, ref pinned);
  3904. if (elementType == null) elementType = CoreSystemTypes.Object;
  3905. if (elementType == null) return null;
  3906. return elementType.GetArrayType(1);
  3907. case ElementType.Array:
  3908. elementType = this.ParseTypeSignature(sigReader, ref pinned);
  3909. if (elementType == null) elementType = CoreSystemTypes.Object;
  3910. if (elementType == null) return null;
  3911. int rank = sigReader.ReadCompressedInt();
  3912. int numSizes = sigReader.ReadCompressedInt();
  3913. int[] sizes = new int[numSizes];
  3914. for (int i = 0; i < numSizes; i++) sizes[i] = sigReader.ReadCompressedInt();
  3915. int numLoBounds = sigReader.ReadCompressedInt();
  3916. int[] loBounds = new int[numLoBounds];
  3917. for (int i = 0; i < numLoBounds; i++) loBounds[i] = sigReader.ReadCompressedInt();
  3918. return elementType.GetArrayType(rank, numSizes, numLoBounds, sizes, loBounds);
  3919. case ElementType.Sentinel: return null;
  3920. case ElementType.Type: return CoreSystemTypes.Type;
  3921. case ElementType.Enum: return this.GetTypeFromSerializedName(ReadSerString(sigReader));
  3922. }
  3923. throw new InvalidMetadataException(ExceptionStrings.MalformedSignature);
  3924. }
  3925. private FunctionPointer/*!*/ ParseFunctionPointer(MemoryCursor/*!*/ sigReader)
  3926. {
  3927. CallingConventionFlags convention = (CallingConventionFlags)sigReader.ReadByte();
  3928. int n = sigReader.ReadCompressedInt();
  3929. TypeNode returnType = this.ParseTypeSignature(sigReader);
  3930. if(returnType == null)
  3931. returnType = CoreSystemTypes.Object;
  3932. TypeNodeList parameterTypes = new TypeNodeList();
  3933. int m = n;
  3934. for(int i = 0; i < n; i++)
  3935. {
  3936. TypeNode t = this.ParseTypeSignature(sigReader);
  3937. if (t == null)
  3938. m = i--;
  3939. else
  3940. parameterTypes.Add(t);
  3941. }
  3942. FunctionPointer fp = FunctionPointer.For(parameterTypes, returnType);
  3943. fp.CallingConvention = convention;
  3944. fp.VarArgStart = m;
  3945. return fp;
  3946. }
  3947. private StatementList ParseMethodBody(Method/*!*/ method, int methodIndex, int RVA)
  3948. {
  3949. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  3950. if (method.DeclaringType.Template != null)
  3951. this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateArguments;
  3952. else
  3953. this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateParameters;
  3954. BodyParser parser = new BodyParser(this, method, methodIndex, RVA);
  3955. StatementList result = parser.ParseStatements();
  3956. this.currentTypeParameters = savedCurrentTypeParameters;
  3957. return result;
  3958. }
  3959. private InstructionList ParseMethodInstructions(Method/*!*/ method, int methodIndex, int RVA)
  3960. {
  3961. TypeNodeList savedCurrentTypeParameters = this.currentTypeParameters;
  3962. if (method.DeclaringType.Template != null)
  3963. this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateArguments;
  3964. else
  3965. this.currentTypeParameters = method.DeclaringType.ConsolidatedTemplateParameters;
  3966. InstructionParser parser = new InstructionParser(this, method, methodIndex, RVA);
  3967. InstructionList result = parser.ParseInstructions();
  3968. this.currentTypeParameters = savedCurrentTypeParameters;
  3969. return result;
  3970. }
  3971. // A version of System.IO.Path.Combine that does not throw exceptions
  3972. private static string Combine(string path1, string path2)
  3973. {
  3974. if(path1 == null || path1.Length == 0)
  3975. return path2;
  3976. if(path2 == null || path2.Length == 0)
  3977. return path1;
  3978. char ch = path2[0];
  3979. if(ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar ||
  3980. (path2.Length >= 2 && path2[1] == Path.VolumeSeparatorChar))
  3981. return path2;
  3982. ch = path1[path1.Length - 1];
  3983. if(ch != Path.DirectorySeparatorChar && ch != Path.AltDirectorySeparatorChar &&
  3984. ch != Path.VolumeSeparatorChar)
  3985. return (path1 + Path.DirectorySeparatorChar + path2);
  3986. return path1 + path2;
  3987. }
  3988. // A version of System.IO.Path.GetDirectoryName that does not throw exceptions
  3989. private static String GetDirectoryName(string path)
  3990. {
  3991. if(path == null)
  3992. return null;
  3993. int length = path.Length;
  3994. for(int i = length; --i >= 0; )
  3995. {
  3996. char ch = path[i];
  3997. if(ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar ||
  3998. ch == Path.VolumeSeparatorChar)
  3999. return path.Substring(0, i);
  4000. }
  4001. return path;
  4002. }
  4003. }
  4004. internal abstract class ILParser
  4005. {
  4006. internal int counter;
  4007. protected Reader/*!*/ reader;
  4008. protected MemoryCursor/*!*/ bodyReader;
  4009. internal int size;
  4010. protected Method/*!*/ method;
  4011. protected int methodIndex;
  4012. protected int RVA;
  4013. protected LocalList/*!*/ locals = new LocalList();
  4014. internal ILParser(Reader/*!*/ reader, Method/*!*/ method, int methodIndex, int RVA)
  4015. {
  4016. this.reader = reader;
  4017. this.bodyReader = reader.tables.GetNewCursor();
  4018. this.method = method;
  4019. this.method.LocalList = this.locals;
  4020. this.methodIndex = methodIndex;
  4021. this.RVA = RVA;
  4022. //^ base();
  4023. }
  4024. protected Expression Parameters(int i)
  4025. {
  4026. if (this.method.IsStatic) return this.method.Parameters[i];
  4027. if (i == 0) return this.method.ThisParameter;
  4028. return this.method.Parameters[i - 1];
  4029. }
  4030. protected void ParseHeader()
  4031. {
  4032. byte header = this.reader.tables.GetMethodBodyHeaderByte(this.RVA);
  4033. if ((header & 0x3) == 2)
  4034. {
  4035. this.size = header >> 2;
  4036. this.bodyReader = this.reader.tables.GetNewCursor();
  4037. this.reader.tables.Skip(size);
  4038. }
  4039. else
  4040. {
  4041. method.InitLocals = (header & 0x10) != 0;
  4042. byte header2 = this.reader.tables.GetByte();
  4043. int fatHeaderSize = header2 >> 4;
  4044. if (fatHeaderSize == 2) return;
  4045. if (fatHeaderSize != 3) throw new InvalidMetadataException(ExceptionStrings.InvalidFatMethodHeader);
  4046. this.reader.tables.Skip(2); //Skip over maxstack. No need to remember it.
  4047. this.size = this.reader.tables.GetInt32();
  4048. int localIndex = this.reader.tables.GetInt32();
  4049. this.bodyReader = this.reader.tables.GetNewCursor();
  4050. this.reader.tables.Skip(size);
  4051. this.reader.tables.AlignTo32BitBoundary();
  4052. while ((header & 0x8) != 0)
  4053. {
  4054. header = this.reader.tables.GetByte();
  4055. if ((header & 3) != 1) throw new InvalidMetadataException(ExceptionStrings.BadMethodHeaderSection);
  4056. if ((header & 0x80) != 0) throw new InvalidMetadataException(ExceptionStrings.TooManyMethodHeaderSections);
  4057. this.ParseExceptionHandlerEntry((header & 0x40) == 0);
  4058. }
  4059. Hashtable localSourceNames = new Hashtable();
  4060. if (this.reader.getDebugSymbols && this.reader.debugReader != null)
  4061. {
  4062. ISymUnmanagedMethod methodInfo = null;
  4063. try
  4064. {
  4065. try
  4066. {
  4067. this.reader.debugReader.GetMethod(0x6000000 | (uint)methodIndex, ref methodInfo);
  4068. if (methodInfo != null)
  4069. {
  4070. ISymUnmanagedScope rootScope = methodInfo.GetRootScope();
  4071. try
  4072. {
  4073. this.reader.GetLocalSourceNames(rootScope, localSourceNames);
  4074. }
  4075. finally
  4076. {
  4077. if (rootScope != null)
  4078. Marshal.ReleaseComObject(rootScope);
  4079. }
  4080. }
  4081. }
  4082. catch (COMException)
  4083. {
  4084. }
  4085. catch (InvalidCastException)
  4086. {
  4087. }
  4088. catch (System.Runtime.InteropServices.InvalidComObjectException) { }
  4089. }
  4090. finally
  4091. {
  4092. if (methodInfo != null)
  4093. Marshal.ReleaseComObject(methodInfo);
  4094. }
  4095. }
  4096. this.reader.GetLocals(localIndex, this.locals, localSourceNames);
  4097. }
  4098. }
  4099. abstract protected void ParseExceptionHandlerEntry(bool smallSection);
  4100. protected byte GetByte()
  4101. {
  4102. this.counter += 1;
  4103. return this.bodyReader.ReadByte();
  4104. }
  4105. protected sbyte GetSByte()
  4106. {
  4107. this.counter += 1;
  4108. return this.bodyReader.ReadSByte();
  4109. }
  4110. protected short GetInt16()
  4111. {
  4112. this.counter += 2;
  4113. return this.bodyReader.ReadInt16();
  4114. }
  4115. protected int GetInt32()
  4116. {
  4117. this.counter += 4;
  4118. return this.bodyReader.ReadInt32();
  4119. }
  4120. protected long GetInt64()
  4121. {
  4122. this.counter += 8;
  4123. return this.bodyReader.ReadInt64();
  4124. }
  4125. protected float GetSingle()
  4126. {
  4127. this.counter += 4;
  4128. return this.bodyReader.ReadSingle();
  4129. }
  4130. protected double GetDouble()
  4131. {
  4132. this.counter += 8;
  4133. return this.bodyReader.ReadDouble();
  4134. }
  4135. protected Member/*!*/ GetMemberFromToken()
  4136. {
  4137. return this.reader.GetMemberFromToken(this.GetInt32());
  4138. }
  4139. protected Member/*!*/ GetMemberFromToken(out TypeNodeList varArgTypes)
  4140. {
  4141. return this.reader.GetMemberFromToken(this.GetInt32(), out varArgTypes);
  4142. }
  4143. protected string/*!*/ GetStringFromToken()
  4144. {
  4145. int tok = this.GetInt32();
  4146. return this.reader.tables.GetUserString(tok & 0xFFFFFF);
  4147. }
  4148. protected OpCode GetOpCode()
  4149. {
  4150. int result = this.GetByte();
  4151. if (result == (int)OpCode.Prefix1)
  4152. result = result << 8 | this.GetByte();
  4153. return (OpCode)result;
  4154. }
  4155. }
  4156. sealed internal class BodyParser : ILParser
  4157. {
  4158. private readonly ExpressionStack/*!*/ operandStack = new ExpressionStack();
  4159. private readonly TrivialHashtable/*!*/ blockMap = new TrivialHashtable();
  4160. private int alignment = -1;
  4161. private bool isReadOnly;
  4162. private bool isTailCall;
  4163. private bool isVolatile;
  4164. private TypeNode constraint;
  4165. internal BodyParser(Reader/*!*/ reader, Method/*!*/ method, int methodIndex, int RVA)
  4166. : base(reader, method, methodIndex, RVA)
  4167. {
  4168. //^ base;
  4169. }
  4170. override protected void ParseExceptionHandlerEntry(bool smallSection)
  4171. {
  4172. int dataSize = this.reader.tables.GetByte();
  4173. int n = (int)(ushort)this.reader.tables.GetInt16();
  4174. if(smallSection)
  4175. n = dataSize / 12;
  4176. else
  4177. n = (dataSize + (n << 8)) / 24;
  4178. if(n < 0)
  4179. n = 0;
  4180. this.method.ExceptionHandlers = new ExceptionHandlerList();
  4181. for(int i = 0; i < n; i++)
  4182. {
  4183. int flags, tryOffset, tryLength, handlerOffset, handlerLength, tokenOrOffset;
  4184. if (smallSection)
  4185. {
  4186. flags = this.reader.tables.GetInt16();
  4187. tryOffset = this.reader.tables.GetUInt16();
  4188. tryLength = this.reader.tables.GetByte();
  4189. handlerOffset = this.reader.tables.GetUInt16();
  4190. handlerLength = this.reader.tables.GetByte();
  4191. }
  4192. else
  4193. {
  4194. flags = this.reader.tables.GetInt32();
  4195. tryOffset = this.reader.tables.GetInt32();
  4196. tryLength = this.reader.tables.GetInt32();
  4197. handlerOffset = this.reader.tables.GetInt32();
  4198. handlerLength = this.reader.tables.GetInt32();
  4199. }
  4200. tokenOrOffset = this.reader.tables.GetInt32();
  4201. ExceptionHandler eh = new ExceptionHandler();
  4202. switch (flags)
  4203. {
  4204. case 0x00:
  4205. eh.HandlerType = NodeType.Catch;
  4206. int pos = this.reader.tables.GetCurrentPosition();
  4207. eh.FilterType = (TypeNode)this.reader.GetMemberFromToken(tokenOrOffset);
  4208. this.reader.tables.SetCurrentPosition(pos);
  4209. break;
  4210. case 0x01:
  4211. eh.HandlerType = NodeType.Filter;
  4212. eh.FilterExpression = Reader.GetOrCreateBlock(blockMap, tokenOrOffset);
  4213. break;
  4214. case 0x02: eh.HandlerType = NodeType.Finally; break;
  4215. case 0x04: eh.HandlerType = NodeType.FaultHandler; break;
  4216. default: throw new InvalidMetadataException(ExceptionStrings.BadExceptionHandlerType);
  4217. }
  4218. eh.TryStartBlock = Reader.GetOrCreateBlock(this.blockMap, tryOffset);
  4219. eh.BlockAfterTryEnd = Reader.GetOrCreateBlock(this.blockMap, tryOffset + tryLength);
  4220. eh.HandlerStartBlock = Reader.GetOrCreateBlock(this.blockMap, handlerOffset);
  4221. eh.BlockAfterHandlerEnd = Reader.GetOrCreateBlock(this.blockMap, handlerOffset + handlerLength);
  4222. this.method.ExceptionHandlers.Add(eh);
  4223. }
  4224. }
  4225. private AssignmentStatement/*!*/ ParseArrayElementAssignment(OpCode opCode)
  4226. {
  4227. Expression rhvalue = PopOperand();
  4228. ExpressionList indexers = new ExpressionList();
  4229. indexers.Add(PopOperand());
  4230. Expression array = PopOperand();
  4231. Indexer indexer = new Indexer(array, indexers);
  4232. TypeNode t = CoreSystemTypes.Object;
  4233. switch (opCode)
  4234. {
  4235. case OpCode.Stelem_I: t = CoreSystemTypes.IntPtr; break;
  4236. case OpCode.Stelem_I1: t = CoreSystemTypes.Int8; break;
  4237. case OpCode.Stelem_I2: t = CoreSystemTypes.Int16; break;
  4238. case OpCode.Stelem_I4: t = CoreSystemTypes.Int32; break;
  4239. case OpCode.Stelem_I8: t = CoreSystemTypes.Int64; break;
  4240. case OpCode.Stelem_R4: t = CoreSystemTypes.Single; break;
  4241. case OpCode.Stelem_R8: t = CoreSystemTypes.Double; break;
  4242. case OpCode.Stelem: t = (TypeNode)this.GetMemberFromToken(); break;
  4243. default:
  4244. ArrayType arrT = array.Type as ArrayType;
  4245. if (arrT != null) t = arrT.ElementType;
  4246. break;
  4247. }
  4248. indexer.ElementType = indexer.Type = t;
  4249. return new AssignmentStatement(indexer, rhvalue);
  4250. }
  4251. private Indexer/*!*/ ParseArrayElementLoad(OpCode opCode, TypeNode elementType)
  4252. {
  4253. ExpressionList indexers = new ExpressionList();
  4254. indexers.Add(PopOperand());
  4255. Expression array = PopOperand();
  4256. Indexer indexer = new Indexer(array, indexers);
  4257. TypeNode t = elementType;
  4258. switch (opCode)
  4259. {
  4260. case OpCode.Ldelem_I1: t = CoreSystemTypes.Int8; break;
  4261. case OpCode.Ldelem_U1: t = CoreSystemTypes.UInt8; break;
  4262. case OpCode.Ldelem_I2: t = CoreSystemTypes.Int16; break;
  4263. case OpCode.Ldelem_U2: t = CoreSystemTypes.UInt16; break;
  4264. case OpCode.Ldelem_I4: t = CoreSystemTypes.Int32; break;
  4265. case OpCode.Ldelem_U4: t = CoreSystemTypes.UInt32; break;
  4266. case OpCode.Ldelem_I8: t = CoreSystemTypes.Int64; break;
  4267. case OpCode.Ldelem_I: t = CoreSystemTypes.IntPtr; break;
  4268. case OpCode.Ldelem_R4: t = CoreSystemTypes.Single; break;
  4269. case OpCode.Ldelem_R8: t = CoreSystemTypes.Double; break;
  4270. case OpCode.Ldelem: t = (TypeNode)this.GetMemberFromToken(); break;
  4271. default:
  4272. if (t != null) break;
  4273. t = CoreSystemTypes.Object;
  4274. ArrayType arrT = array.Type as ArrayType;
  4275. if (arrT != null) t = arrT.ElementType;
  4276. break;
  4277. }
  4278. indexer.ElementType = indexer.Type = t;
  4279. return indexer;
  4280. }
  4281. private UnaryExpression/*!*/ ParseArrayElementLoadAddress()
  4282. {
  4283. TypeNode elemType = (TypeNode)this.GetMemberFromToken();
  4284. return new UnaryExpression(this.ParseArrayElementLoad(0, elemType), this.isReadOnly ? NodeType.ReadOnlyAddressOf : NodeType.AddressOf, elemType.GetReferenceType());
  4285. }
  4286. private static UnaryExpression/*!*/ SetType(UnaryExpression/*!*/ uex)
  4287. {
  4288. if (uex == null || uex.Operand == null) return uex;
  4289. TypeNode elemType = uex.Operand.Type;
  4290. if (elemType == null) return uex;
  4291. uex.Type = elemType.GetReferenceType();
  4292. return uex;
  4293. }
  4294. private BinaryExpression/*!*/ ParseBinaryComparison(NodeType oper)
  4295. {
  4296. Expression op2 = PopOperand();
  4297. Expression op1 = PopOperand();
  4298. BinaryExpression result = new BinaryExpression(op1, op2, oper);
  4299. result.Type = CoreSystemTypes.Int32;
  4300. return result;
  4301. }
  4302. private BinaryExpression/*!*/ ParseBinaryOperation(NodeType oper)
  4303. {
  4304. Expression op2 = PopOperand();
  4305. Expression op1 = PopOperand();
  4306. BinaryExpression result = new BinaryExpression(op1, op2, oper);
  4307. result.Type = op1.Type;
  4308. if (result.Type == null) result.Type = op2.Type;
  4309. return result;
  4310. }
  4311. private UnaryExpression/*!*/ ParseUnaryOperation(NodeType oper)
  4312. {
  4313. Expression op = PopOperand();
  4314. return new UnaryExpression(op, oper, op.Type);
  4315. }
  4316. private Branch/*!*/ ParseBranch(NodeType operatorType, int operandCount, bool shortOffset, bool unordered)
  4317. {
  4318. return this.ParseBranch(operatorType, operandCount, shortOffset, unordered, false);
  4319. }
  4320. private Branch/*!*/ ParseBranch(NodeType operatorType, int operandCount, bool shortOffset, bool unordered, bool leavesExceptionBlock)
  4321. {
  4322. Expression operand2 = operandCount > 1 ? PopOperand() : null;
  4323. Expression operand1 = operandCount > 0 ? PopOperand() : null;
  4324. Expression condition = operandCount > 1 ? (Expression)new BinaryExpression(operand1, operand2, operatorType) :
  4325. (operandCount > 0 ? (operatorType == NodeType.Nop ? operand1 : (Expression)new UnaryExpression(operand1, operatorType)) : null);
  4326. int targetAddress = shortOffset ? this.GetSByte() : this.GetInt32();
  4327. Block targetBlock = (Block)this.blockMap[targetAddress + this.counter + 1];
  4328. Debug.Assert(targetBlock != null);
  4329. if (targetAddress >= 0 && !this.reader.preserveShortBranches) shortOffset = false;
  4330. return new Branch(condition, targetBlock, shortOffset, unordered, leavesExceptionBlock);
  4331. }
  4332. private MethodCall/*!*/ ParseCall(NodeType typeOfCall, out bool isStatement)
  4333. {
  4334. TypeNodeList varArgTypes;
  4335. Method meth = (Method)this.GetMemberFromToken(out varArgTypes);
  4336. int numVarArgs = varArgTypes == null ? 0 : varArgTypes.Count;
  4337. isStatement = BodyParser.TypeIsVoid(meth.ReturnType);
  4338. int n = meth.Parameters == null ? 0 : meth.Parameters.Count;
  4339. if(typeOfCall == NodeType.Jmp)
  4340. n = 0;
  4341. else
  4342. n += numVarArgs;
  4343. Expression[] args = new Expression[n];
  4344. ExpressionList arguments = new ExpressionList();
  4345. for(int i = n - 1; i >= 0; i--)
  4346. args[i] = PopOperand();
  4347. for(int i = 0; i < n; i++)
  4348. arguments.Add(args[i]);
  4349. if(varArgTypes != null)
  4350. {
  4351. for (int i = n - 1, j = numVarArgs; j > 0; j--, i--)
  4352. {
  4353. Expression e = arguments[i];
  4354. TypeNode t = varArgTypes[j - 1];
  4355. if (e != null && t != null) e.Type = t;
  4356. }
  4357. }
  4358. Expression thisob = meth.IsStatic ? null : PopOperand();
  4359. MemberBinding methBinding = new MemberBinding(thisob, meth);
  4360. MethodCall result = new MethodCall(methBinding, arguments, typeOfCall);
  4361. result.Type = meth.ReturnType;
  4362. result.IsTailCall = this.isTailCall;
  4363. if(this.constraint != null)
  4364. {
  4365. result.Constraint = this.constraint;
  4366. this.constraint = null;
  4367. }
  4368. return result;
  4369. }
  4370. private static bool TypeIsVoid(TypeNode t)
  4371. {
  4372. if (t == null) return false;
  4373. for (; ; )
  4374. {
  4375. switch (t.NodeType)
  4376. {
  4377. case NodeType.OptionalModifier:
  4378. case NodeType.RequiredModifier:
  4379. t = ((TypeModifier)t).ModifiedType;
  4380. break;
  4381. default:
  4382. return t == CoreSystemTypes.Void;
  4383. }
  4384. }
  4385. }
  4386. private MethodCall/*!*/ ParseCalli(out bool isStatement)
  4387. {
  4388. FunctionPointer fp = this.reader.GetCalliSignature(this.GetInt32());
  4389. if(fp == null)
  4390. throw new InvalidMetadataException(ExceptionStrings.BadCalliSignature);
  4391. isStatement = BodyParser.TypeIsVoid(fp.ReturnType);
  4392. int n = fp.ParameterTypes.Count;
  4393. Expression[] args = new Expression[n + 1];
  4394. ExpressionList arguments = new ExpressionList();
  4395. for(int i = n; i >= 0; i--)
  4396. args[i] = PopOperand();
  4397. for(int i = 0; i <= n; i++)
  4398. arguments.Add(args[i]);
  4399. Expression thisob = fp.IsStatic ? null : PopOperand();
  4400. MemberBinding methBinding = new MemberBinding(thisob, fp);
  4401. MethodCall result = new MethodCall(methBinding, arguments, NodeType.Calli);
  4402. result.Type = fp.ReturnType;
  4403. result.IsTailCall = this.isTailCall;
  4404. return result;
  4405. }
  4406. private static Expression/*!*/ ParseTypeCheck(Expression operand, TypeNode type, NodeType typeOfCheck)
  4407. {
  4408. TypeNode etype = type;
  4409. if (typeOfCheck == NodeType.Unbox) etype = type.GetReferenceType();
  4410. Expression expr = new BinaryExpression(operand, new Literal(type, CoreSystemTypes.Type), typeOfCheck, etype);
  4411. return expr;
  4412. }
  4413. private Construct/*!*/ ParseConstruct()
  4414. {
  4415. TypeNodeList varArgTypes;
  4416. Method meth = (Method)this.GetMemberFromToken(out varArgTypes);
  4417. int n = meth.Parameters.Count;
  4418. Expression[] args = new Expression[n];
  4419. ExpressionList arguments = new ExpressionList();
  4420. for(int i = n - 1; i >= 0; i--)
  4421. args[i] = PopOperand();
  4422. for(int i = 0; i < n; i++)
  4423. arguments.Add(args[i]);
  4424. Construct result = new Construct(new MemberBinding(null, meth), arguments);
  4425. result.Type = meth.DeclaringType;
  4426. return result;
  4427. }
  4428. private AssignmentStatement/*!*/ ParseCopyObject()
  4429. {
  4430. TypeNode type = (TypeNode)this.GetMemberFromToken();
  4431. Expression rhaddr = PopOperand();
  4432. Expression lhaddr = PopOperand();
  4433. return new AssignmentStatement(new AddressDereference(lhaddr, type, this.isVolatile, this.alignment), new AddressDereference(rhaddr, type));
  4434. }
  4435. private UnaryExpression /*!*/ ParseLoadRuntimeMetadataToken()
  4436. {
  4437. Expression expr = null;
  4438. TypeNode exprType = null;
  4439. Member member = this.GetMemberFromToken();
  4440. TypeNode t = member as TypeNode;
  4441. if (t == null)
  4442. {
  4443. exprType = (member.NodeType == NodeType.Field)
  4444. ? CoreSystemTypes.RuntimeFieldHandle : CoreSystemTypes.RuntimeMethodHandle;
  4445. expr = new MemberBinding(null, member);
  4446. }
  4447. else
  4448. {
  4449. exprType = CoreSystemTypes.RuntimeTypeHandle;
  4450. expr = new Literal(t, CoreSystemTypes.Type);
  4451. }
  4452. return new UnaryExpression(expr, NodeType.Ldtoken, exprType);
  4453. }
  4454. private AssignmentStatement/*!*/ ParseInitObject()
  4455. {
  4456. TypeNode type = (TypeNode)this.GetMemberFromToken();
  4457. Expression lhaddr = PopOperand();
  4458. return new AssignmentStatement(new AddressDereference(lhaddr, type, this.isVolatile, this.alignment), new Literal(null, CoreSystemTypes.Object));
  4459. }
  4460. private ConstructArray/*!*/ ParseNewArray()
  4461. {
  4462. TypeNode type = (TypeNode)this.GetMemberFromToken();
  4463. ExpressionList sizes = new ExpressionList();
  4464. sizes.Add(PopOperand());
  4465. ConstructArray result = new ConstructArray(type, sizes, null);
  4466. result.Type = type.GetArrayType(1);
  4467. return result;
  4468. }
  4469. internal StatementList/*!*/ ParseStatements()
  4470. {
  4471. this.ParseHeader();
  4472. if(this.size == 0)
  4473. return new StatementList();
  4474. this.CreateBlocksForBranchTargets();
  4475. StatementList result = new StatementList();
  4476. Block currentBlock = null;
  4477. while(this.counter < size)
  4478. {
  4479. if (currentBlock == null)
  4480. {
  4481. currentBlock = Reader.GetOrCreateBlock(this.blockMap, this.counter);
  4482. result.Add(currentBlock);
  4483. }
  4484. bool endOfBasicBlock = this.ParseStatement(currentBlock);
  4485. if(endOfBasicBlock)
  4486. currentBlock = null;
  4487. }
  4488. result.Add(Reader.GetOrCreateBlock(this.blockMap, this.counter));
  4489. return result;
  4490. }
  4491. private bool ParseStatement(Block/*!*/ block)
  4492. {
  4493. //parse instructions and put in expression tree until an assignment, void call, branch target, or branch is encountered
  4494. StatementList statementList = block.Statements;
  4495. Expression expr = null;
  4496. Statement statement = null;
  4497. bool transferStatement = false;
  4498. int startingAddress = 0;
  4499. SourceContext sourceContext = new SourceContext();
  4500. sourceContext.StartPos = this.counter;
  4501. if (this.method.contextForOffset != null)
  4502. {
  4503. object sctx = this.method.contextForOffset[this.counter + 1];
  4504. if (sctx != null) sourceContext = (SourceContext)sctx;
  4505. }
  4506. while (true)
  4507. {
  4508. bool isStatement = false;
  4509. startingAddress = this.counter + 1; //Add one so that it is never zero (the latter means no entry to the TrivialHashtable)
  4510. OpCode opCode = this.GetOpCode();
  4511. switch (opCode)
  4512. {
  4513. case OpCode.Nop: statement = new Statement(NodeType.Nop); goto done;
  4514. case OpCode.Break: statement = new Statement(NodeType.DebugBreak); goto done;
  4515. case OpCode.Ldarg_0: expr = this.Parameters(0); break;
  4516. case OpCode.Ldarg_1: expr = this.Parameters(1); break;
  4517. case OpCode.Ldarg_2: expr = this.Parameters(2); break;
  4518. case OpCode.Ldarg_3: expr = this.Parameters(3); break;
  4519. case OpCode.Ldloc_0: expr = this.locals[0]; break;
  4520. case OpCode.Ldloc_1: expr = this.locals[1]; break;
  4521. case OpCode.Ldloc_2: expr = this.locals[2]; break;
  4522. case OpCode.Ldloc_3: expr = this.locals[3]; break;
  4523. case OpCode.Stloc_0: statement = new AssignmentStatement(this.locals[0], PopOperand()); goto done;
  4524. case OpCode.Stloc_1: statement = new AssignmentStatement(this.locals[1], PopOperand()); goto done;
  4525. case OpCode.Stloc_2: statement = new AssignmentStatement(this.locals[2], PopOperand()); goto done;
  4526. case OpCode.Stloc_3: statement = new AssignmentStatement(this.locals[3], PopOperand()); goto done;
  4527. case OpCode.Ldarg_S: expr = this.Parameters(this.GetByte()); break;
  4528. case OpCode.Ldarga_S: expr = SetType(new UnaryExpression(this.Parameters(this.GetByte()), NodeType.AddressOf)); break;
  4529. case OpCode.Starg_S: statement = new AssignmentStatement(this.Parameters(this.GetByte()), PopOperand()); goto done;
  4530. case OpCode.Ldloc_S: expr = this.locals[this.GetByte()]; break;
  4531. case OpCode.Ldloca_S: expr = SetType(new UnaryExpression(this.locals[this.GetByte()], NodeType.AddressOf)); break;
  4532. case OpCode.Stloc_S: statement = new AssignmentStatement(this.locals[this.GetByte()], PopOperand()); goto done;
  4533. case OpCode.Ldnull: expr = new Literal(null, CoreSystemTypes.Object); break;
  4534. case OpCode.Ldc_I4_M1: expr = new Literal(-1, CoreSystemTypes.Int32); break;
  4535. case OpCode.Ldc_I4_0: expr = new Literal(0, CoreSystemTypes.Int32); break;
  4536. case OpCode.Ldc_I4_1: expr = new Literal(1, CoreSystemTypes.Int32); break;
  4537. case OpCode.Ldc_I4_2: expr = new Literal(2, CoreSystemTypes.Int32); break;
  4538. case OpCode.Ldc_I4_3: expr = new Literal(3, CoreSystemTypes.Int32); break;
  4539. case OpCode.Ldc_I4_4: expr = new Literal(4, CoreSystemTypes.Int32); break;
  4540. case OpCode.Ldc_I4_5: expr = new Literal(5, CoreSystemTypes.Int32); break;
  4541. case OpCode.Ldc_I4_6: expr = new Literal(6, CoreSystemTypes.Int32); break;
  4542. case OpCode.Ldc_I4_7: expr = new Literal(7, CoreSystemTypes.Int32); break;
  4543. case OpCode.Ldc_I4_8: expr = new Literal(8, CoreSystemTypes.Int32); break;
  4544. case OpCode.Ldc_I4_S: expr = new Literal((int)this.GetSByte(), CoreSystemTypes.Int32); break;
  4545. case OpCode.Ldc_I4: expr = new Literal(this.GetInt32(), CoreSystemTypes.Int32); break;
  4546. case OpCode.Ldc_I8: expr = new Literal(this.GetInt64(), CoreSystemTypes.Int64); break;
  4547. case OpCode.Ldc_R4: expr = new Literal(this.GetSingle(), CoreSystemTypes.Single); break;
  4548. case OpCode.Ldc_R8: expr = new Literal(this.GetDouble(), CoreSystemTypes.Double); break;
  4549. case OpCode.Dup: statement = new ExpressionStatement(new Expression(NodeType.Dup)); goto done;
  4550. case OpCode.Pop: statement = new ExpressionStatement(new UnaryExpression(PopOperand(), NodeType.Pop)); goto done;
  4551. case OpCode.Jmp: expr = this.ParseCall(NodeType.Jmp, out isStatement); if (isStatement) goto done; break;
  4552. case OpCode.Call: expr = this.ParseCall(NodeType.Call, out isStatement); if (isStatement) goto done; break;
  4553. case OpCode.Calli: expr = this.ParseCalli(out isStatement); if (isStatement) goto done; break;
  4554. case OpCode.Ret:
  4555. Expression retVal = BodyParser.TypeIsVoid(this.method.ReturnType) ? null : PopOperand();
  4556. statement = new Return(retVal);
  4557. transferStatement = true; goto done;
  4558. case OpCode.Br_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false); transferStatement = true; goto done;
  4559. case OpCode.Brfalse_S: statement = this.ParseBranch(NodeType.LogicalNot, 1, true, false); transferStatement = true; goto done;
  4560. case OpCode.Brtrue_S: statement = this.ParseBranch(NodeType.Nop, 1, true, false); transferStatement = true; goto done;
  4561. case OpCode.Beq_S: statement = this.ParseBranch(NodeType.Eq, 2, true, false); transferStatement = true; goto done;
  4562. case OpCode.Bge_S: statement = this.ParseBranch(NodeType.Ge, 2, true, false); transferStatement = true; goto done;
  4563. case OpCode.Bgt_S: statement = this.ParseBranch(NodeType.Gt, 2, true, false); transferStatement = true; goto done;
  4564. case OpCode.Ble_S: statement = this.ParseBranch(NodeType.Le, 2, true, false); transferStatement = true; goto done;
  4565. case OpCode.Blt_S: statement = this.ParseBranch(NodeType.Lt, 2, true, false); transferStatement = true; goto done;
  4566. case OpCode.Bne_Un_S: statement = this.ParseBranch(NodeType.Ne, 2, true, true); transferStatement = true; goto done;
  4567. case OpCode.Bge_Un_S: statement = this.ParseBranch(NodeType.Ge, 2, true, true); transferStatement = true; goto done;
  4568. case OpCode.Bgt_Un_S: statement = this.ParseBranch(NodeType.Gt, 2, true, true); transferStatement = true; goto done;
  4569. case OpCode.Ble_Un_S: statement = this.ParseBranch(NodeType.Le, 2, true, true); transferStatement = true; goto done;
  4570. case OpCode.Blt_Un_S: statement = this.ParseBranch(NodeType.Lt, 2, true, true); transferStatement = true; goto done;
  4571. case OpCode.Br: statement = this.ParseBranch(NodeType.Nop, 0, false, false); transferStatement = true; goto done;
  4572. case OpCode.Brfalse: statement = this.ParseBranch(NodeType.LogicalNot, 1, false, false); transferStatement = true; goto done;
  4573. case OpCode.Brtrue: statement = this.ParseBranch(NodeType.Nop, 1, false, false); transferStatement = true; goto done;
  4574. case OpCode.Beq: statement = this.ParseBranch(NodeType.Eq, 2, false, false); transferStatement = true; goto done;
  4575. case OpCode.Bge: statement = this.ParseBranch(NodeType.Ge, 2, false, false); transferStatement = true; goto done;
  4576. case OpCode.Bgt: statement = this.ParseBranch(NodeType.Gt, 2, false, false); transferStatement = true; goto done;
  4577. case OpCode.Ble: statement = this.ParseBranch(NodeType.Le, 2, false, false); transferStatement = true; goto done;
  4578. case OpCode.Blt: statement = this.ParseBranch(NodeType.Lt, 2, false, false); transferStatement = true; goto done;
  4579. case OpCode.Bne_Un: statement = this.ParseBranch(NodeType.Ne, 2, false, true); transferStatement = true; goto done;
  4580. case OpCode.Bge_Un: statement = this.ParseBranch(NodeType.Ge, 2, false, true); transferStatement = true; goto done;
  4581. case OpCode.Bgt_Un: statement = this.ParseBranch(NodeType.Gt, 2, false, true); transferStatement = true; goto done;
  4582. case OpCode.Ble_Un: statement = this.ParseBranch(NodeType.Le, 2, false, true); transferStatement = true; goto done;
  4583. case OpCode.Blt_Un: statement = this.ParseBranch(NodeType.Lt, 2, false, true); transferStatement = true; goto done;
  4584. case OpCode.Switch: statement = this.ParseSwitchInstruction(); transferStatement = true; goto done;
  4585. case OpCode.Ldind_I1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int8, this.isVolatile, this.alignment); break;
  4586. case OpCode.Ldind_U1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt8, this.isVolatile, this.alignment); break;
  4587. case OpCode.Ldind_I2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int16, this.isVolatile, this.alignment); break;
  4588. case OpCode.Ldind_U2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt16, this.isVolatile, this.alignment); break;
  4589. case OpCode.Ldind_I4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int32, this.isVolatile, this.alignment); break;
  4590. case OpCode.Ldind_U4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt32, this.isVolatile, this.alignment); break;
  4591. case OpCode.Ldind_I8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int64, this.isVolatile, this.alignment); break;
  4592. case OpCode.Ldind_I: expr = new AddressDereference(PopOperand(), CoreSystemTypes.IntPtr, this.isVolatile, this.alignment); break;
  4593. case OpCode.Ldind_R4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Single, this.isVolatile, this.alignment); break;
  4594. case OpCode.Ldind_R8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Double, this.isVolatile, this.alignment); break;
  4595. case OpCode.Ldind_Ref: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Object, this.isVolatile, this.alignment); break;
  4596. case OpCode.Stind_Ref: statement = this.ParseStoreIndirect(CoreSystemTypes.Object); goto done;
  4597. case OpCode.Stind_I1: statement = this.ParseStoreIndirect(CoreSystemTypes.Int8); goto done;
  4598. case OpCode.Stind_I2: statement = this.ParseStoreIndirect(CoreSystemTypes.Int16); goto done;
  4599. case OpCode.Stind_I4: statement = this.ParseStoreIndirect(CoreSystemTypes.Int32); goto done;
  4600. case OpCode.Stind_I8: statement = this.ParseStoreIndirect(CoreSystemTypes.Int64); goto done;
  4601. case OpCode.Stind_R4: statement = this.ParseStoreIndirect(CoreSystemTypes.Single); goto done;
  4602. case OpCode.Stind_R8: statement = this.ParseStoreIndirect(CoreSystemTypes.Double); goto done;
  4603. case OpCode.Add: expr = this.ParseBinaryOperation(NodeType.Add); break;
  4604. case OpCode.Sub: expr = this.ParseBinaryOperation(NodeType.Sub); break;
  4605. case OpCode.Mul: expr = this.ParseBinaryOperation(NodeType.Mul); break;
  4606. case OpCode.Div: expr = this.ParseBinaryOperation(NodeType.Div); break;
  4607. case OpCode.Div_Un: expr = this.ParseBinaryOperation(NodeType.Div_Un); break;
  4608. case OpCode.Rem: expr = this.ParseBinaryOperation(NodeType.Rem); break;
  4609. case OpCode.Rem_Un: expr = this.ParseBinaryOperation(NodeType.Rem_Un); break;
  4610. case OpCode.And: expr = this.ParseBinaryOperation(NodeType.And); break;
  4611. case OpCode.Or: expr = this.ParseBinaryOperation(NodeType.Or); break;
  4612. case OpCode.Xor: expr = this.ParseBinaryOperation(NodeType.Xor); break;
  4613. case OpCode.Shl: expr = this.ParseBinaryOperation(NodeType.Shl); break;
  4614. case OpCode.Shr: expr = this.ParseBinaryOperation(NodeType.Shr); break;
  4615. case OpCode.Shr_Un: expr = this.ParseBinaryOperation(NodeType.Shr_Un); break;
  4616. case OpCode.Neg: expr = this.ParseUnaryOperation(NodeType.Neg); break;
  4617. case OpCode.Not: expr = this.ParseUnaryOperation(NodeType.Not); break;
  4618. case OpCode.Conv_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I1, CoreSystemTypes.Int8); break;
  4619. case OpCode.Conv_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I2, CoreSystemTypes.Int16); break;
  4620. case OpCode.Conv_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I4, CoreSystemTypes.Int32); break;
  4621. case OpCode.Conv_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I8, CoreSystemTypes.Int64); break;
  4622. case OpCode.Conv_R4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R4, CoreSystemTypes.Single); break;
  4623. case OpCode.Conv_R8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R8, CoreSystemTypes.Double); break;
  4624. case OpCode.Conv_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U4, CoreSystemTypes.UInt32); break;
  4625. case OpCode.Conv_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U8, CoreSystemTypes.UInt64); break;
  4626. case OpCode.Callvirt: expr = this.ParseCall(NodeType.Callvirt, out isStatement); if (isStatement) goto done; break;
  4627. case OpCode.Cpobj: statement = this.ParseCopyObject(); goto done;
  4628. case OpCode.Ldobj: expr = new AddressDereference(PopOperand(), (TypeNode)this.GetMemberFromToken(), this.isVolatile, this.alignment); break;
  4629. case OpCode.Ldstr: expr = new Literal(this.GetStringFromToken(), CoreSystemTypes.String); break;
  4630. case OpCode.Newobj: expr = this.ParseConstruct(); break;
  4631. case OpCode.Castclass: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Castclass); break;
  4632. case OpCode.Isinst: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Isinst); break;
  4633. case OpCode.Conv_R_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R_Un, CoreSystemTypes.Double); break;
  4634. case OpCode.Unbox: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Unbox); break;
  4635. case OpCode.Throw: statement = new Throw(PopOperand()); transferStatement = true; goto done;
  4636. case OpCode.Ldfld:
  4637. expr = new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment);
  4638. break;
  4639. case OpCode.Ldflda:
  4640. expr = SetType(new UnaryExpression(new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf));
  4641. break;
  4642. case OpCode.Stfld: statement = this.ParseStoreField(); goto done;
  4643. case OpCode.Ldsfld: expr = new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment); break;
  4644. case OpCode.Ldsflda: expr = SetType(new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break;
  4645. case OpCode.Stsfld: statement = new AssignmentStatement(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), PopOperand()); goto done;
  4646. case OpCode.Stobj: statement = this.ParseStoreIndirect((TypeNode)this.GetMemberFromToken()); goto done;
  4647. case OpCode.Conv_Ovf_I1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1_Un, CoreSystemTypes.Int8); break;
  4648. case OpCode.Conv_Ovf_I2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2_Un, CoreSystemTypes.Int16); break;
  4649. case OpCode.Conv_Ovf_I4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4_Un, CoreSystemTypes.Int32); break;
  4650. case OpCode.Conv_Ovf_I8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8_Un, CoreSystemTypes.Int64); break;
  4651. case OpCode.Conv_Ovf_U1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1_Un, CoreSystemTypes.UInt8); break;
  4652. case OpCode.Conv_Ovf_U2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2_Un, CoreSystemTypes.UInt16); break;
  4653. case OpCode.Conv_Ovf_U4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4_Un, CoreSystemTypes.UInt32); break;
  4654. case OpCode.Conv_Ovf_U8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8_Un, CoreSystemTypes.UInt64); break;
  4655. case OpCode.Conv_Ovf_I_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I_Un, CoreSystemTypes.IntPtr); break;
  4656. case OpCode.Conv_Ovf_U_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U_Un, CoreSystemTypes.UIntPtr); break;
  4657. case OpCode.Box:
  4658. TypeNode t = (TypeNode)this.GetMemberFromToken();
  4659. TypeNode bt = t is EnumNode ? CoreSystemTypes.Enum : CoreSystemTypes.ValueType;
  4660. expr = new BinaryExpression(PopOperand(), new Literal(t, CoreSystemTypes.Type), NodeType.Box, bt); break;
  4661. case OpCode.Newarr: expr = this.ParseNewArray(); break;
  4662. case OpCode.Ldlen: expr = new UnaryExpression(PopOperand(), NodeType.Ldlen, CoreSystemTypes.UIntPtr); break;
  4663. case OpCode.Ldelema: expr = this.ParseArrayElementLoadAddress(); break;
  4664. case OpCode.Ldelem_I1:
  4665. case OpCode.Ldelem_U1:
  4666. case OpCode.Ldelem_I2:
  4667. case OpCode.Ldelem_U2:
  4668. case OpCode.Ldelem_I4:
  4669. case OpCode.Ldelem_U4:
  4670. case OpCode.Ldelem_I8:
  4671. case OpCode.Ldelem_I:
  4672. case OpCode.Ldelem_R4:
  4673. case OpCode.Ldelem_R8:
  4674. case OpCode.Ldelem_Ref: expr = this.ParseArrayElementLoad(opCode, null); break;
  4675. case OpCode.Stelem_I:
  4676. case OpCode.Stelem_I1:
  4677. case OpCode.Stelem_I2:
  4678. case OpCode.Stelem_I4:
  4679. case OpCode.Stelem_I8:
  4680. case OpCode.Stelem_R4:
  4681. case OpCode.Stelem_R8:
  4682. case OpCode.Stelem_Ref: statement = this.ParseArrayElementAssignment(opCode); goto done;
  4683. case OpCode.Ldelem: expr = this.ParseArrayElementLoad(opCode, null); break;
  4684. case OpCode.Stelem: statement = this.ParseArrayElementAssignment(opCode); goto done;
  4685. case OpCode.Unbox_Any: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.UnboxAny); break;
  4686. case OpCode.Conv_Ovf_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1, CoreSystemTypes.Int8); break;
  4687. case OpCode.Conv_Ovf_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1, CoreSystemTypes.UInt8); break;
  4688. case OpCode.Conv_Ovf_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2, CoreSystemTypes.Int16); break;
  4689. case OpCode.Conv_Ovf_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2, CoreSystemTypes.UInt16); break;
  4690. case OpCode.Conv_Ovf_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4, CoreSystemTypes.Int32); break;
  4691. case OpCode.Conv_Ovf_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4, CoreSystemTypes.UInt32); break;
  4692. case OpCode.Conv_Ovf_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8, CoreSystemTypes.Int64); break;
  4693. case OpCode.Conv_Ovf_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8, CoreSystemTypes.UInt64); break;
  4694. case OpCode.Refanyval: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Refanyval, CoreSystemTypes.IntPtr); break;
  4695. case OpCode.Ckfinite: expr = this.ParseUnaryOperation(NodeType.Ckfinite); break;
  4696. case OpCode.Mkrefany: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Mkrefany, CoreSystemTypes.DynamicallyTypedReference); break;
  4697. case OpCode.Ldtoken: expr = ParseLoadRuntimeMetadataToken(); break;
  4698. case OpCode.Conv_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U2, CoreSystemTypes.UInt16); break;
  4699. case OpCode.Conv_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U1, CoreSystemTypes.UInt8); break;
  4700. case OpCode.Conv_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I, CoreSystemTypes.IntPtr); break;
  4701. case OpCode.Conv_Ovf_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I, CoreSystemTypes.IntPtr); break;
  4702. case OpCode.Conv_Ovf_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U, CoreSystemTypes.UIntPtr); break;
  4703. case OpCode.Add_Ovf: expr = this.ParseBinaryOperation(NodeType.Add_Ovf); break;
  4704. case OpCode.Add_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Add_Ovf_Un); break;
  4705. case OpCode.Mul_Ovf: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf); break;
  4706. case OpCode.Mul_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf_Un); break;
  4707. case OpCode.Sub_Ovf: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf); break;
  4708. case OpCode.Sub_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf_Un); break;
  4709. case OpCode.Endfinally: statement = new EndFinally(); transferStatement = true; goto done;
  4710. case OpCode.Leave: statement = this.ParseBranch(NodeType.Nop, 0, false, false, true); transferStatement = true; goto done;
  4711. case OpCode.Leave_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false, true); transferStatement = true; goto done;
  4712. case OpCode.Stind_I: statement = this.ParseStoreIndirect(CoreSystemTypes.IntPtr); goto done;
  4713. case OpCode.Conv_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U, CoreSystemTypes.UIntPtr); break;
  4714. case OpCode.Arglist: expr = new Expression(NodeType.Arglist, CoreSystemTypes.ArgIterator); break;
  4715. case OpCode.Ceq: expr = this.ParseBinaryComparison(NodeType.Ceq); break;
  4716. case OpCode.Cgt: expr = this.ParseBinaryComparison(NodeType.Cgt); break;
  4717. case OpCode.Cgt_Un: expr = this.ParseBinaryComparison(NodeType.Cgt_Un); break;
  4718. case OpCode.Clt: expr = this.ParseBinaryComparison(NodeType.Clt); break;
  4719. case OpCode.Clt_Un: expr = this.ParseBinaryComparison(NodeType.Clt_Un); break;
  4720. case OpCode.Ldftn: expr = new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldftn, CoreSystemTypes.IntPtr); break;
  4721. case OpCode.Ldvirtftn: expr = new BinaryExpression(PopOperand(), new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldvirtftn, CoreSystemTypes.IntPtr); break;
  4722. case OpCode.Ldarg: expr = this.Parameters((ushort)this.GetInt16()); break;
  4723. case OpCode.Ldarga: expr = SetType(new UnaryExpression(this.Parameters((ushort)this.GetInt16()), NodeType.AddressOf)); break;
  4724. case OpCode.Starg: statement = new AssignmentStatement(this.Parameters((ushort)this.GetInt16()), PopOperand()); goto done;
  4725. case OpCode.Ldloc: expr = this.locals[(ushort)this.GetInt16()]; break;
  4726. case OpCode.Ldloca: expr = SetType(new UnaryExpression(this.locals[(ushort)this.GetInt16()], NodeType.AddressOf)); break;
  4727. case OpCode.Stloc: statement = new AssignmentStatement(this.locals[(ushort)this.GetInt16()], PopOperand()); goto done;
  4728. case OpCode.Localloc: expr = new UnaryExpression(PopOperand(), NodeType.Localloc, CoreSystemTypes.Void); break;
  4729. case OpCode.Endfilter: statement = new EndFilter(PopOperand()); transferStatement = true; goto done;
  4730. case OpCode.Unaligned_: this.alignment = this.GetByte(); continue;
  4731. case OpCode.Volatile_: this.isVolatile = true; continue;
  4732. case OpCode.Tail_: this.isTailCall = true; continue;
  4733. case OpCode.Initobj: statement = this.ParseInitObject(); goto done;
  4734. case OpCode.Constrained_: this.constraint = this.GetMemberFromToken() as TypeNode; continue;
  4735. case OpCode.Cpblk: expr = this.ParseTernaryOperation(NodeType.Cpblk); goto done;
  4736. case OpCode.Initblk: expr = this.ParseTernaryOperation(NodeType.Initblk); goto done;
  4737. case OpCode.Rethrow: statement = new Throw(null); statement.NodeType = NodeType.Rethrow; transferStatement = true; goto done;
  4738. case OpCode.Sizeof: expr = new UnaryExpression(new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Sizeof, CoreSystemTypes.Int32); break;
  4739. case OpCode.Refanytype: expr = new UnaryExpression(PopOperand(), NodeType.Refanytype, CoreSystemTypes.RuntimeTypeHandle); break;
  4740. case OpCode.Readonly_: this.isReadOnly = true; continue;
  4741. default: throw new InvalidMetadataException(ExceptionStrings.UnknownOpCode);
  4742. }
  4743. if (this.blockMap[this.counter + 1] != null)
  4744. {
  4745. transferStatement = true; //Falls through to the next basic block, so implicitly a "transfer" statement
  4746. goto done;
  4747. }
  4748. //^ assume expr != null;
  4749. this.operandStack.Push(expr);
  4750. this.isReadOnly = false;
  4751. this.isVolatile = false;
  4752. this.isTailCall = false;
  4753. this.alignment = -1;
  4754. }
  4755. done:
  4756. for (int i = 0; i <= this.operandStack.top; i++)
  4757. {
  4758. Expression e = this.operandStack.elements[i];
  4759. //^ assume e != null;
  4760. Statement s = new ExpressionStatement(e);
  4761. statementList.Add(s);
  4762. }
  4763. this.operandStack.top = -1;
  4764. if (statement == null)
  4765. statement = new ExpressionStatement(expr);
  4766. statement.SourceContext = sourceContext;
  4767. statementList.Add(statement);
  4768. if (transferStatement) return true;
  4769. return this.blockMap[this.counter + 1] != null;
  4770. }
  4771. private AssignmentStatement ParseStoreField()
  4772. {
  4773. Expression rhvalue = PopOperand();
  4774. Expression thisob = PopOperand();
  4775. AssignmentStatement s = new AssignmentStatement(new MemberBinding(thisob, this.GetMemberFromToken(), this.isVolatile, this.alignment), rhvalue);
  4776. return s;
  4777. }
  4778. private AssignmentStatement ParseStoreIndirect(TypeNode type)
  4779. {
  4780. Expression rhvalue = PopOperand();
  4781. Expression lhaddr = PopOperand();
  4782. return new AssignmentStatement(new AddressDereference(lhaddr, type, this.isVolatile, this.alignment), rhvalue);
  4783. }
  4784. private SwitchInstruction ParseSwitchInstruction()
  4785. {
  4786. int numTargets = this.GetInt32();
  4787. int offset = this.counter + numTargets * 4;
  4788. BlockList targetList = new BlockList();
  4789. for(int i = 0; i < numTargets; i++)
  4790. {
  4791. int targetAddress = this.GetInt32() + offset;
  4792. targetList.Add(Reader.GetOrCreateBlock(this.blockMap, targetAddress));
  4793. }
  4794. return new SwitchInstruction(PopOperand(), targetList);
  4795. }
  4796. private TernaryExpression ParseTernaryOperation(NodeType oper)
  4797. {
  4798. Expression op3 = PopOperand();
  4799. Expression op2 = PopOperand();
  4800. Expression op1 = PopOperand();
  4801. return new TernaryExpression(op1, op2, op3, oper, null);
  4802. }
  4803. private void CreateBlocksForBranchTargets()
  4804. {
  4805. int savedPosition = bodyReader.Position;
  4806. while (this.counter < this.size)
  4807. this.ProcessOneILInstruction();
  4808. this.counter = 0;
  4809. bodyReader.Position = savedPosition;
  4810. }
  4811. private void ProcessOneILInstruction()
  4812. {
  4813. OpCode opc = this.GetOpCode();
  4814. switch (opc)
  4815. {
  4816. case OpCode.Ldarg_S:
  4817. case OpCode.Ldarga_S:
  4818. case OpCode.Starg_S:
  4819. case OpCode.Ldloc_S:
  4820. case OpCode.Ldloca_S:
  4821. case OpCode.Stloc_S:
  4822. case OpCode.Ldc_I4_S:
  4823. this.GetByte(); return;
  4824. case OpCode.Ldc_I4:
  4825. case OpCode.Jmp:
  4826. case OpCode.Call:
  4827. case OpCode.Calli:
  4828. case OpCode.Callvirt:
  4829. case OpCode.Cpobj:
  4830. case OpCode.Ldobj:
  4831. case OpCode.Ldstr:
  4832. case OpCode.Newobj:
  4833. case OpCode.Castclass:
  4834. case OpCode.Isinst:
  4835. case OpCode.Unbox:
  4836. case OpCode.Ldfld:
  4837. case OpCode.Ldflda:
  4838. case OpCode.Stfld:
  4839. case OpCode.Ldsfld:
  4840. case OpCode.Ldsflda:
  4841. case OpCode.Stsfld:
  4842. case OpCode.Stobj:
  4843. case OpCode.Box:
  4844. case OpCode.Newarr:
  4845. case OpCode.Ldelema:
  4846. case OpCode.Ldelem:
  4847. case OpCode.Stelem:
  4848. case OpCode.Unbox_Any:
  4849. case OpCode.Refanyval:
  4850. case OpCode.Mkrefany:
  4851. case OpCode.Ldtoken:
  4852. this.GetInt32(); return;
  4853. case OpCode.Ldc_I8:
  4854. this.GetInt64(); return;
  4855. case OpCode.Ldc_R4:
  4856. this.GetSingle(); return;
  4857. case OpCode.Ldc_R8:
  4858. this.GetDouble(); return;
  4859. case OpCode.Br_S:
  4860. case OpCode.Brfalse_S:
  4861. case OpCode.Brtrue_S:
  4862. case OpCode.Beq_S:
  4863. case OpCode.Bge_S:
  4864. case OpCode.Bgt_S:
  4865. case OpCode.Ble_S:
  4866. case OpCode.Blt_S:
  4867. case OpCode.Bne_Un_S:
  4868. case OpCode.Bge_Un_S:
  4869. case OpCode.Bgt_Un_S:
  4870. case OpCode.Ble_Un_S:
  4871. case OpCode.Blt_Un_S:
  4872. case OpCode.Leave_S:
  4873. this.SkipBranch(true); return;
  4874. case OpCode.Br:
  4875. case OpCode.Brfalse:
  4876. case OpCode.Brtrue:
  4877. case OpCode.Beq:
  4878. case OpCode.Bge:
  4879. case OpCode.Bgt:
  4880. case OpCode.Ble:
  4881. case OpCode.Blt:
  4882. case OpCode.Bne_Un:
  4883. case OpCode.Bge_Un:
  4884. case OpCode.Bgt_Un:
  4885. case OpCode.Ble_Un:
  4886. case OpCode.Blt_Un:
  4887. case OpCode.Leave:
  4888. this.SkipBranch(false); return;
  4889. case OpCode.Switch:
  4890. this.SkipSwitch(); return;
  4891. case OpCode.Ldftn:
  4892. case OpCode.Ldvirtftn:
  4893. case OpCode.Initobj:
  4894. case OpCode.Constrained_:
  4895. case OpCode.Sizeof:
  4896. this.GetInt32(); return;
  4897. case OpCode.Ldarg:
  4898. case OpCode.Ldarga:
  4899. case OpCode.Ldloc:
  4900. case OpCode.Ldloca:
  4901. case OpCode.Starg:
  4902. case OpCode.Stloc:
  4903. this.GetInt16(); return;
  4904. case OpCode.Unaligned_:
  4905. this.GetByte(); return;
  4906. default:
  4907. return;
  4908. }
  4909. }
  4910. private void SkipBranch(bool shortOffset)
  4911. {
  4912. int offset = shortOffset ? this.GetSByte() : this.GetInt32();
  4913. Reader.GetOrCreateBlock(blockMap, this.counter + offset);
  4914. }
  4915. private void SkipSwitch()
  4916. {
  4917. int numCases = this.GetInt32();
  4918. int offset = this.counter + numCases * 4;
  4919. for (int i = 0; i < numCases; i++)
  4920. {
  4921. int targetAddress = this.GetInt32() + offset;
  4922. Reader.GetOrCreateBlock(this.blockMap, targetAddress);
  4923. }
  4924. }
  4925. private Expression PopOperand()
  4926. {
  4927. return this.operandStack.Pop();
  4928. }
  4929. }
  4930. internal class InstructionParser : ILParser
  4931. {
  4932. private readonly TrivialHashtable/*!*/ ehMap;
  4933. internal InstructionParser(Reader/*!*/ reader, Method/*!*/ method, int methodIndex, int RVA)
  4934. : base(reader, method, methodIndex, RVA)
  4935. {
  4936. this.ehMap = new TrivialHashtable();
  4937. }
  4938. override protected void ParseExceptionHandlerEntry(bool smallSection)
  4939. {
  4940. TrivialHashtable tryMap = new TrivialHashtable();
  4941. int dataSize = this.reader.tables.GetByte();
  4942. int n = (int)(ushort)this.reader.tables.GetInt16();
  4943. if (smallSection)
  4944. n = dataSize / 12;
  4945. else
  4946. n = (dataSize + (n << 8)) / 24;
  4947. for (int i = 0; i < n; i++)
  4948. {
  4949. Instruction matchingInstruction;
  4950. int flags, tryOffset, tryLength, handlerOffset, handlerLength, tokenOrOffset;
  4951. if (smallSection)
  4952. {
  4953. flags = this.reader.tables.GetInt16();
  4954. tryOffset = this.reader.tables.GetUInt16();
  4955. tryLength = this.reader.tables.GetByte();
  4956. handlerOffset = this.reader.tables.GetUInt16();
  4957. handlerLength = this.reader.tables.GetByte();
  4958. }
  4959. else
  4960. {
  4961. flags = this.reader.tables.GetInt32();
  4962. tryOffset = this.reader.tables.GetInt32();
  4963. tryLength = this.reader.tables.GetInt32();
  4964. handlerOffset = this.reader.tables.GetInt32();
  4965. handlerLength = this.reader.tables.GetInt32();
  4966. }
  4967. tokenOrOffset = this.reader.tables.GetInt32();
  4968. if (tryMap[tryOffset + tryLength] == null)
  4969. {
  4970. matchingInstruction = this.AddInstruction(OpCode._Try, tryOffset);
  4971. this.AddInstruction(OpCode._EndTry, tryOffset + tryLength, matchingInstruction);
  4972. tryMap[tryOffset + tryLength] = String.Empty;
  4973. }
  4974. switch (flags)
  4975. {
  4976. case 0x00:
  4977. int pos = this.reader.tables.GetCurrentPosition();
  4978. TypeNode catchType = (TypeNode)this.reader.GetMemberFromToken(tokenOrOffset);
  4979. this.reader.tables.SetCurrentPosition(pos);
  4980. matchingInstruction = this.AddInstruction(OpCode._Catch, handlerOffset, catchType);
  4981. this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction);
  4982. break;
  4983. case 0x01:
  4984. matchingInstruction = this.AddInstruction(OpCode._Filter, tokenOrOffset);
  4985. this.AddInstruction(OpCode._EndFilter, handlerOffset, matchingInstruction);
  4986. matchingInstruction = this.AddInstruction(OpCode._Catch, handlerOffset);
  4987. this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction);
  4988. break;
  4989. case 0x02:
  4990. matchingInstruction = this.AddInstruction(OpCode._Finally, handlerOffset);
  4991. this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction);
  4992. break;
  4993. case 0x04:
  4994. matchingInstruction = this.AddInstruction(OpCode._Fault, handlerOffset);
  4995. this.AddInstruction(OpCode._EndHandler, handlerOffset + handlerLength, matchingInstruction);
  4996. break;
  4997. default: throw new InvalidMetadataException(ExceptionStrings.BadExceptionHandlerType);
  4998. }
  4999. }
  5000. }
  5001. private Instruction AddInstruction(OpCode opCode, int offset)
  5002. {
  5003. return this.AddInstruction(opCode, offset, null);
  5004. }
  5005. private Instruction AddInstruction(OpCode opCode, int offset, object value)
  5006. {
  5007. Instruction instruction = new Instruction(opCode, offset, value);
  5008. InstructionList instructions = (InstructionList)this.ehMap[offset + 1];
  5009. if(instructions == null)
  5010. this.ehMap[offset + 1] = instructions = new InstructionList();
  5011. instructions.Add(instruction);
  5012. if(this.method.contextForOffset != null)
  5013. {
  5014. object sctx = this.method.contextForOffset[offset + 1];
  5015. if(sctx != null)
  5016. instruction.SourceContext = (SourceContext)sctx;
  5017. }
  5018. return instruction;
  5019. }
  5020. private List<int> ParseSwitchInstruction()
  5021. {
  5022. int numTargets = this.GetInt32();
  5023. List<int> result = new List<int>();
  5024. int offset = this.counter + numTargets * 4;
  5025. for(int i = 0; i < numTargets; i++)
  5026. {
  5027. int targetAddress = this.GetInt32() + offset;
  5028. result.Add(targetAddress);
  5029. }
  5030. return result;
  5031. }
  5032. internal InstructionList ParseInstructions()
  5033. {
  5034. this.ParseHeader();
  5035. if(this.size == 0)
  5036. return new InstructionList();
  5037. InstructionList result = new InstructionList();
  5038. result.Add(new Instruction(OpCode._Locals, 0, this.locals));
  5039. while(this.counter <= size)
  5040. {
  5041. InstructionList instructions = (InstructionList)this.ehMap[this.counter + 1];
  5042. if(instructions != null)
  5043. {
  5044. for(int i = 0; i < instructions.Count; i++)
  5045. result.Add(instructions[i]);
  5046. }
  5047. if(this.counter < size)
  5048. result.Add(this.ParseInstruction());
  5049. else
  5050. break;
  5051. }
  5052. return result;
  5053. }
  5054. private SourceContext sourceContext = new SourceContext();
  5055. internal Instruction ParseInstruction()
  5056. {
  5057. if (this.counter >= this.size)
  5058. return null;
  5059. int offset = this.counter;
  5060. if (this.method.contextForOffset != null)
  5061. {
  5062. object sctx = this.method.contextForOffset[offset + 1];
  5063. if (sctx != null) this.sourceContext = (SourceContext)sctx;
  5064. }
  5065. object value = null;
  5066. OpCode opCode = this.GetOpCode();
  5067. switch (opCode)
  5068. {
  5069. case OpCode.Nop:
  5070. case OpCode.Break:
  5071. break;
  5072. case OpCode.Ldarg_0: value = this.Parameters(0); break;
  5073. case OpCode.Ldarg_1: value = this.Parameters(1); break;
  5074. case OpCode.Ldarg_2: value = this.Parameters(2); break;
  5075. case OpCode.Ldarg_3: value = this.Parameters(3); break;
  5076. case OpCode.Ldloc_0: value = this.locals[0]; break;
  5077. case OpCode.Ldloc_1: value = this.locals[1]; break;
  5078. case OpCode.Ldloc_2: value = this.locals[2]; break;
  5079. case OpCode.Ldloc_3: value = this.locals[3]; break;
  5080. case OpCode.Stloc_0: value = this.locals[0]; break;
  5081. case OpCode.Stloc_1: value = this.locals[1]; break;
  5082. case OpCode.Stloc_2: value = this.locals[2]; break;
  5083. case OpCode.Stloc_3: value = this.locals[3]; break;
  5084. case OpCode.Ldarg_S:
  5085. case OpCode.Ldarga_S:
  5086. case OpCode.Starg_S:
  5087. value = this.Parameters(this.GetByte()); break;
  5088. case OpCode.Ldloc_S:
  5089. case OpCode.Ldloca_S:
  5090. case OpCode.Stloc_S:
  5091. value = this.locals[this.GetByte()]; break;
  5092. case OpCode.Ldnull:
  5093. break;
  5094. case OpCode.Ldc_I4_M1: value = (Int32)(-1); break;
  5095. case OpCode.Ldc_I4_0: value = (Int32)0; break;
  5096. case OpCode.Ldc_I4_1: value = (Int32)1; break;
  5097. case OpCode.Ldc_I4_2: value = (Int32)2; break;
  5098. case OpCode.Ldc_I4_3: value = (Int32)3; break;
  5099. case OpCode.Ldc_I4_4: value = (Int32)4; break;
  5100. case OpCode.Ldc_I4_5: value = (Int32)5; break;
  5101. case OpCode.Ldc_I4_6: value = (Int32)6; break;
  5102. case OpCode.Ldc_I4_7: value = (Int32)7; break;
  5103. case OpCode.Ldc_I4_8: value = (Int32)8; break;
  5104. case OpCode.Ldc_I4_S: value = (Int32)this.GetSByte(); break;
  5105. case OpCode.Ldc_I4: value = this.GetInt32(); break;
  5106. case OpCode.Ldc_I8: value = this.GetInt64(); break;
  5107. case OpCode.Ldc_R4: value = this.GetSingle(); break;
  5108. case OpCode.Ldc_R8: value = this.GetDouble(); break;
  5109. case OpCode.Dup:
  5110. case OpCode.Pop:
  5111. break;
  5112. case OpCode.Jmp:
  5113. case OpCode.Call:
  5114. value = (Method)this.GetMemberFromToken(); break;
  5115. case OpCode.Calli:
  5116. value = (FunctionPointer)this.reader.GetCalliSignature(this.GetInt32()); break;
  5117. case OpCode.Ret: break;
  5118. case OpCode.Br_S:
  5119. case OpCode.Brfalse_S:
  5120. case OpCode.Brtrue_S:
  5121. case OpCode.Beq_S:
  5122. case OpCode.Bge_S:
  5123. case OpCode.Bgt_S:
  5124. case OpCode.Ble_S:
  5125. case OpCode.Blt_S:
  5126. case OpCode.Bne_Un_S:
  5127. case OpCode.Bge_Un_S:
  5128. case OpCode.Bgt_Un_S:
  5129. case OpCode.Ble_Un_S:
  5130. case OpCode.Blt_Un_S:
  5131. value = this.counter + 1 + this.GetSByte(); break;
  5132. case OpCode.Br:
  5133. case OpCode.Brfalse:
  5134. case OpCode.Brtrue:
  5135. case OpCode.Beq:
  5136. case OpCode.Bge:
  5137. case OpCode.Bgt:
  5138. case OpCode.Ble:
  5139. case OpCode.Blt:
  5140. case OpCode.Bne_Un:
  5141. case OpCode.Bge_Un:
  5142. case OpCode.Bgt_Un:
  5143. case OpCode.Ble_Un:
  5144. case OpCode.Blt_Un:
  5145. value = this.counter + 4 + this.GetInt32(); break;
  5146. case OpCode.Switch:
  5147. value = this.ParseSwitchInstruction(); break;
  5148. case OpCode.Ldind_I1:
  5149. case OpCode.Ldind_U1:
  5150. case OpCode.Ldind_I2:
  5151. case OpCode.Ldind_U2:
  5152. case OpCode.Ldind_I4:
  5153. case OpCode.Ldind_U4:
  5154. case OpCode.Ldind_I8:
  5155. case OpCode.Ldind_I:
  5156. case OpCode.Ldind_R4:
  5157. case OpCode.Ldind_R8:
  5158. case OpCode.Ldind_Ref:
  5159. case OpCode.Stind_Ref:
  5160. case OpCode.Stind_I1:
  5161. case OpCode.Stind_I2:
  5162. case OpCode.Stind_I4:
  5163. case OpCode.Stind_I8:
  5164. case OpCode.Stind_R4:
  5165. case OpCode.Stind_R8:
  5166. case OpCode.Add:
  5167. case OpCode.Sub:
  5168. case OpCode.Mul:
  5169. case OpCode.Div:
  5170. case OpCode.Div_Un:
  5171. case OpCode.Rem:
  5172. case OpCode.Rem_Un:
  5173. case OpCode.And:
  5174. case OpCode.Or:
  5175. case OpCode.Xor:
  5176. case OpCode.Shl:
  5177. case OpCode.Shr:
  5178. case OpCode.Shr_Un:
  5179. case OpCode.Neg:
  5180. case OpCode.Not:
  5181. case OpCode.Conv_I1:
  5182. case OpCode.Conv_I2:
  5183. case OpCode.Conv_I4:
  5184. case OpCode.Conv_I8:
  5185. case OpCode.Conv_R4:
  5186. case OpCode.Conv_R8:
  5187. case OpCode.Conv_U4:
  5188. case OpCode.Conv_U8:
  5189. break;
  5190. case OpCode.Callvirt: value = (Method)this.GetMemberFromToken(); break;
  5191. case OpCode.Cpobj:
  5192. case OpCode.Ldobj:
  5193. value = (TypeNode)this.GetMemberFromToken(); break;
  5194. case OpCode.Ldstr: value = this.GetStringFromToken(); break;
  5195. case OpCode.Newobj: value = (Method)this.GetMemberFromToken(); break;
  5196. case OpCode.Castclass:
  5197. case OpCode.Isinst:
  5198. value = (TypeNode)this.GetMemberFromToken(); break;
  5199. case OpCode.Conv_R_Un: break;
  5200. case OpCode.Unbox: value = (TypeNode)this.GetMemberFromToken(); break;
  5201. case OpCode.Throw: break;
  5202. case OpCode.Ldfld:
  5203. case OpCode.Ldflda:
  5204. case OpCode.Stfld:
  5205. case OpCode.Ldsfld:
  5206. case OpCode.Ldsflda:
  5207. case OpCode.Stsfld:
  5208. case OpCode.Stobj:
  5209. value = this.GetMemberFromToken(); break;
  5210. case OpCode.Conv_Ovf_I1_Un:
  5211. case OpCode.Conv_Ovf_I2_Un:
  5212. case OpCode.Conv_Ovf_I4_Un:
  5213. case OpCode.Conv_Ovf_I8_Un:
  5214. case OpCode.Conv_Ovf_U1_Un:
  5215. case OpCode.Conv_Ovf_U2_Un:
  5216. case OpCode.Conv_Ovf_U4_Un:
  5217. case OpCode.Conv_Ovf_U8_Un:
  5218. case OpCode.Conv_Ovf_I_Un:
  5219. case OpCode.Conv_Ovf_U_Un:
  5220. break;
  5221. case OpCode.Box:
  5222. case OpCode.Newarr: value = (TypeNode)this.GetMemberFromToken(); break;
  5223. case OpCode.Ldlen: break;
  5224. case OpCode.Ldelema: value = (TypeNode)this.GetMemberFromToken(); break;
  5225. case OpCode.Ldelem_I1:
  5226. case OpCode.Ldelem_U1:
  5227. case OpCode.Ldelem_I2:
  5228. case OpCode.Ldelem_U2:
  5229. case OpCode.Ldelem_I4:
  5230. case OpCode.Ldelem_U4:
  5231. case OpCode.Ldelem_I8:
  5232. case OpCode.Ldelem_I:
  5233. case OpCode.Ldelem_R4:
  5234. case OpCode.Ldelem_R8:
  5235. case OpCode.Ldelem_Ref:
  5236. case OpCode.Stelem_I:
  5237. case OpCode.Stelem_I1:
  5238. case OpCode.Stelem_I2:
  5239. case OpCode.Stelem_I4:
  5240. case OpCode.Stelem_I8:
  5241. case OpCode.Stelem_R4:
  5242. case OpCode.Stelem_R8:
  5243. case OpCode.Stelem_Ref:
  5244. break;
  5245. case OpCode.Ldelem:
  5246. value = (TypeNode)this.GetMemberFromToken();
  5247. break;
  5248. case OpCode.Stelem: value = (TypeNode)this.GetMemberFromToken(); break;
  5249. case OpCode.Unbox_Any: value = this.GetMemberFromToken(); break;
  5250. case OpCode.Conv_Ovf_I1:
  5251. case OpCode.Conv_Ovf_U1:
  5252. case OpCode.Conv_Ovf_I2:
  5253. case OpCode.Conv_Ovf_U2:
  5254. case OpCode.Conv_Ovf_I4:
  5255. case OpCode.Conv_Ovf_U4:
  5256. case OpCode.Conv_Ovf_I8:
  5257. case OpCode.Conv_Ovf_U8:
  5258. break;
  5259. case OpCode.Refanyval: value = this.GetMemberFromToken(); break;
  5260. case OpCode.Ckfinite: break;
  5261. case OpCode.Mkrefany: value = this.GetMemberFromToken(); break;
  5262. case OpCode.Ldtoken: value = this.GetMemberFromToken(); break;
  5263. case OpCode.Conv_U2:
  5264. case OpCode.Conv_U1:
  5265. case OpCode.Conv_I:
  5266. case OpCode.Conv_Ovf_I:
  5267. case OpCode.Conv_Ovf_U:
  5268. case OpCode.Add_Ovf:
  5269. case OpCode.Add_Ovf_Un:
  5270. case OpCode.Mul_Ovf:
  5271. case OpCode.Mul_Ovf_Un:
  5272. case OpCode.Sub_Ovf:
  5273. case OpCode.Sub_Ovf_Un:
  5274. case OpCode.Endfinally:
  5275. break;
  5276. case OpCode.Leave: value = this.counter + 4 + this.GetInt32(); break;
  5277. case OpCode.Leave_S: value = this.counter + 1 + this.GetSByte(); break;
  5278. case OpCode.Stind_I:
  5279. case OpCode.Conv_U:
  5280. case OpCode.Prefix7:
  5281. case OpCode.Prefix6:
  5282. case OpCode.Prefix5:
  5283. case OpCode.Prefix4:
  5284. case OpCode.Prefix3:
  5285. case OpCode.Prefix2:
  5286. case OpCode.Prefix1:
  5287. case OpCode.Arglist:
  5288. case OpCode.Ceq:
  5289. case OpCode.Cgt:
  5290. case OpCode.Cgt_Un:
  5291. case OpCode.Clt:
  5292. case OpCode.Clt_Un:
  5293. break;
  5294. case OpCode.Ldftn:
  5295. case OpCode.Ldvirtftn:
  5296. value = this.GetMemberFromToken(); break;
  5297. case OpCode.Ldarg:
  5298. case OpCode.Ldarga:
  5299. case OpCode.Starg:
  5300. value = this.Parameters(this.GetInt16()); break;
  5301. case OpCode.Ldloc:
  5302. case OpCode.Ldloca:
  5303. case OpCode.Stloc:
  5304. value = this.locals[this.GetInt16()]; break;
  5305. case OpCode.Localloc:
  5306. case OpCode.Endfilter:
  5307. break;
  5308. case OpCode.Unaligned_: value = this.GetByte(); break;
  5309. case OpCode.Volatile_:
  5310. case OpCode.Tail_:
  5311. break;
  5312. case OpCode.Initobj: value = (TypeNode)this.GetMemberFromToken(); break;
  5313. case OpCode.Constrained_: value = this.GetMemberFromToken() as TypeNode; break;
  5314. case OpCode.Cpblk:
  5315. case OpCode.Initblk:
  5316. break;
  5317. case OpCode.Rethrow:
  5318. break;
  5319. case OpCode.Sizeof: value = this.GetMemberFromToken(); break;
  5320. case OpCode.Refanytype:
  5321. case OpCode.Readonly_:
  5322. break;
  5323. default: throw new InvalidMetadataException(String.Format(CultureInfo.CurrentCulture,
  5324. ExceptionStrings.UnknownOpCodeEncountered, opCode.ToString("x")));
  5325. }
  5326. Instruction instruction = new Instruction(opCode, offset, value);
  5327. instruction.SourceContext = this.sourceContext;
  5328. return instruction;
  5329. }
  5330. }
  5331. internal class ExpressionStack
  5332. {
  5333. internal Expression[]/*!*/ elements = new Expression[64];
  5334. internal int top = -1;
  5335. internal ExpressionStack()
  5336. {
  5337. //^ base();
  5338. }
  5339. private void Grow()
  5340. {
  5341. int n = this.elements.Length;
  5342. Expression[] newElements = new Expression[n + 64];
  5343. for (int i = 0; i < n; i++) newElements[i] = this.elements[i];
  5344. this.elements = newElements;
  5345. }
  5346. internal Expression/*!*/ Pop()
  5347. {
  5348. if (this.top < 0) return new Expression(NodeType.Pop);
  5349. Expression e = this.elements[this.top--];
  5350. //^ assume e != null;
  5351. return e;
  5352. }
  5353. internal void Push(Expression/*!*/ e)
  5354. {
  5355. if (++this.top >= this.elements.Length) this.Grow();
  5356. this.elements[this.top] = e;
  5357. }
  5358. }
  5359. /// <summary>
  5360. /// A thin wrapper for a synchronized System.Collections.Hashtable that inserts and strips WeakReference wrappers for the values stored in the table.
  5361. /// </summary>
  5362. internal class SynchronizedWeakDictionary : IDictionary
  5363. {
  5364. private Hashtable/*!*/ Hashtable = System.Collections.Hashtable.Synchronized(new Hashtable());
  5365. internal SynchronizedWeakDictionary()
  5366. {
  5367. //^ base();
  5368. }
  5369. public void Add(object/*!*/ key, object value)
  5370. {
  5371. this.Hashtable.Add(key, new WeakReference(value));
  5372. }
  5373. public void Clear()
  5374. {
  5375. this.Hashtable.Clear();
  5376. }
  5377. public bool Contains(object/*!*/ key)
  5378. {
  5379. return this.Hashtable.Contains(key);
  5380. }
  5381. public IDictionaryEnumerator/*!*/ GetEnumerator()
  5382. {
  5383. return this.Hashtable.GetEnumerator();
  5384. }
  5385. public bool IsFixedSize
  5386. {
  5387. get { return false; }
  5388. }
  5389. public bool IsReadOnly
  5390. {
  5391. get { return false; }
  5392. }
  5393. public ICollection/*!*/ Keys
  5394. {
  5395. get { return this.Hashtable.Keys; }
  5396. }
  5397. public void Remove(object/*!*/ key)
  5398. {
  5399. this.Hashtable.Remove(key);
  5400. }
  5401. public ICollection/*!*/ Values
  5402. {
  5403. get { return new WeakValuesCollection(this.Hashtable.Values); }
  5404. }
  5405. public object this[object/*!*/ key]
  5406. {
  5407. get
  5408. {
  5409. WeakReference wref = (WeakReference)this.Hashtable[key];
  5410. if (wref == null) return null;
  5411. return wref.Target;
  5412. }
  5413. set
  5414. {
  5415. this.Hashtable[key] = new WeakReference(value);
  5416. }
  5417. }
  5418. public void CopyTo(Array/*!*/ array, int index)
  5419. {
  5420. IEnumerator enumerator = this.GetEnumerator();
  5421. for (int i = 0; enumerator.MoveNext(); i++)
  5422. array.SetValue(enumerator.Current, index + i);
  5423. }
  5424. public int Count
  5425. {
  5426. get { return this.Hashtable.Count; }
  5427. }
  5428. public bool IsSynchronized
  5429. {
  5430. get { return false; }
  5431. }
  5432. public object/*!*/ SyncRoot
  5433. {
  5434. get { return this.Hashtable.SyncRoot; }
  5435. }
  5436. IEnumerator/*!*/ IEnumerable.GetEnumerator()
  5437. {
  5438. return new WeakValuesEnumerator(this.Hashtable.GetEnumerator());
  5439. }
  5440. }
  5441. internal class WeakValuesCollection : ICollection
  5442. {
  5443. private ICollection/*!*/ collection;
  5444. internal WeakValuesCollection(ICollection/*!*/ collection)
  5445. {
  5446. this.collection = collection;
  5447. //^ base();
  5448. }
  5449. public void CopyTo(Array/*!*/ array, int index)
  5450. {
  5451. IEnumerator enumerator = this.GetEnumerator();
  5452. for (int i = 0; enumerator.MoveNext(); i++)
  5453. array.SetValue(enumerator.Current, index + i);
  5454. }
  5455. public int Count
  5456. {
  5457. get { return this.collection.Count; }
  5458. }
  5459. public bool IsSynchronized
  5460. {
  5461. get { return this.collection.IsSynchronized; }
  5462. }
  5463. public object/*!*/ SyncRoot
  5464. {
  5465. get { return this.collection.SyncRoot; }
  5466. }
  5467. public IEnumerator/*!*/ GetEnumerator()
  5468. {
  5469. return new WeakValuesEnumerator(this.collection.GetEnumerator());
  5470. }
  5471. }
  5472. internal class WeakValuesEnumerator : IEnumerator
  5473. {
  5474. private IEnumerator/*!*/ enumerator;
  5475. internal WeakValuesEnumerator(IEnumerator/*!*/ enumerator)
  5476. {
  5477. this.enumerator = enumerator;
  5478. //^ base();
  5479. }
  5480. public object Current
  5481. {
  5482. get
  5483. {
  5484. object curr = this.enumerator.Current;
  5485. if (curr is DictionaryEntry)
  5486. {
  5487. DictionaryEntry dicEntry = (DictionaryEntry)curr;
  5488. curr = dicEntry.Value;
  5489. }
  5490. WeakReference wref = curr as WeakReference;
  5491. if (wref != null) return wref.Target;
  5492. return null;
  5493. }
  5494. }
  5495. public bool MoveNext()
  5496. {
  5497. return this.enumerator.MoveNext();
  5498. }
  5499. public void Reset()
  5500. {
  5501. this.enumerator.Reset();
  5502. }
  5503. }
  5504. [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44")]
  5505. internal interface IMetaDataImport
  5506. {
  5507. }
  5508. internal class EmptyImporter : IMetaDataImport
  5509. {
  5510. }
  5511. }