MDTypeElems.cs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /*
  2. * PERWAPI - An API for Reading and Writing PE Files
  3. *
  4. * Copyright (c) Diane Corney, Queensland University of Technology, 2004.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the PERWAPI Copyright as included with this
  8. * distribution in the file PERWAPIcopyright.rtf.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY as is explained in the copyright notice.
  12. *
  13. * The author may be contacted at d.corney@qut.edu.au
  14. *
  15. * Version Date: 26/01/07
  16. */
  17. using System;
  18. using System.IO;
  19. using System.Collections;
  20. using System.Collections.Generic;
  21. using System.Security.Cryptography;
  22. namespace QUT.PERWAPI
  23. {
  24. /**************************************************************************/
  25. /// <summary>
  26. /// Base class for all IL types
  27. /// </summary>
  28. public abstract class Type : MetaDataElement
  29. {
  30. protected byte typeIndex;
  31. /// <summary>
  32. /// The following is only used for TypeSpecs and ClassSpecs. kjg
  33. /// </summary>
  34. internal bool typeSpecAdded = false; // so that MetaDataOut can reset it
  35. /*-------------------- Constructors ---------------------------------*/
  36. internal Type(byte tyIx) { typeIndex = tyIx; }
  37. internal byte GetTypeIndex() { return typeIndex; }
  38. internal virtual bool SameType(Type tstType)
  39. {
  40. return this == tstType;
  41. }
  42. internal virtual void TypeSig(MemoryStream str)
  43. {
  44. throw new TypeSignatureException(this.GetType().AssemblyQualifiedName +
  45. " doesn't have a type signature!!");
  46. }
  47. public virtual string TypeName()
  48. {
  49. return "NoTypeName";
  50. }
  51. internal virtual void WriteType(CILWriter output)
  52. {
  53. throw new NotYetImplementedException("Writing types for CIL");
  54. }
  55. internal virtual void WriteName(CILWriter output)
  56. {
  57. WriteType(output);
  58. }
  59. internal virtual Type AddTypeSpec(MetaDataOut md)
  60. {
  61. if (!isDef()) BuildMDTables(md);
  62. return this;
  63. }
  64. }
  65. /**************************************************************************/
  66. /// <summary>
  67. /// Descriptor for a custom modifier of a type (modopt or modreq)
  68. /// </summary>
  69. public class CustomModifiedType : Type
  70. {
  71. Type type;
  72. Class cmodType;
  73. /*-------------------- Constructors ---------------------------------*/
  74. /// <summary>
  75. /// Create a new custom modifier for a type
  76. /// </summary>
  77. /// <param name="type">the type to be modified</param>
  78. /// <param name="cmod">the modifier</param>
  79. /// <param name="cmodType">the type reference to be associated with the type</param>
  80. public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
  81. : base((byte)cmod)
  82. {
  83. this.type = type;
  84. this.cmodType = cmodType;
  85. }
  86. /*------------------------- public set and get methods --------------------------*/
  87. public void SetModifiedType(Type modType) { type = modType; }
  88. public Type GetModifiedType() { return type; }
  89. public void SetModifingType(Class mod) { cmodType = mod; }
  90. public Class GetModifingType() { return cmodType; }
  91. public void SetModifier(CustomModifier cmod) { typeIndex = (byte)cmod; }
  92. public CustomModifier GetModifier() { return (CustomModifier)typeIndex; }
  93. /*----------------------------- internal functions ------------------------------*/
  94. internal override bool SameType(Type tstType)
  95. {
  96. if (this == tstType) return true;
  97. if (tstType is CustomModifiedType)
  98. {
  99. CustomModifiedType cmTstType = (CustomModifiedType)tstType;
  100. return type.SameType(cmTstType.type) &&
  101. cmodType.SameType(cmTstType.cmodType);
  102. }
  103. return false;
  104. }
  105. internal sealed override void TypeSig(MemoryStream str)
  106. {
  107. str.WriteByte(typeIndex);
  108. MetaDataOut.CompressNum(BlobUtil.CompressUInt(cmodType.TypeDefOrRefToken()), str);
  109. type.TypeSig(str);
  110. }
  111. internal sealed override void BuildTables(MetaDataOut md)
  112. {
  113. if (!(cmodType is ClassDef))
  114. cmodType.BuildMDTables(md);
  115. if (!(type is ClassDef))
  116. type.BuildMDTables(md);
  117. }
  118. }
  119. /**************************************************************************/
  120. internal class Pinned : Type
  121. {
  122. internal Pinned() : base((byte)ElementType.Pinned) { }
  123. }
  124. /**************************************************************************/
  125. internal class Sentinel : Type
  126. {
  127. internal Sentinel() : base((byte)ElementType.Sentinel) { }
  128. }
  129. /**************************************************************************/
  130. public abstract class TypeSpec : Type
  131. {
  132. uint sigIx = 0;
  133. //internal bool typeSpecAdded = false; // so that MetaDataOut can reset it
  134. /*-------------------- Constructors ---------------------------------*/
  135. internal TypeSpec(byte typeIx)
  136. : base(typeIx)
  137. {
  138. tabIx = MDTable.TypeSpec;
  139. }
  140. internal static void Read(PEReader buff, TableRow[] specs)
  141. {
  142. for (int i = 0; i < specs.Length; i++)
  143. {
  144. specs[i] = new UnresolvedTypeSpec(buff, i);
  145. //specs[i] = buff.GetBlobType(null,null,buff.GetBlobIx());
  146. //if (specs[i] is GenericParam) {
  147. // Console.WriteLine("GenericParam in TypeSpec table at pos " + i);
  148. //}
  149. }
  150. }
  151. internal override sealed Type AddTypeSpec(MetaDataOut md)
  152. {
  153. if (typeSpecAdded) return this;
  154. md.ConditionalAddTypeSpec(this);
  155. BuildMDTables(md);
  156. typeSpecAdded = true;
  157. return this;
  158. }
  159. internal override void BuildSignatures(MetaDataOut md)
  160. {
  161. MemoryStream str = new MemoryStream();
  162. TypeSig(str);
  163. sigIx = md.AddToBlobHeap(str.ToArray());
  164. done = false;
  165. }
  166. internal static uint Size(MetaData md)
  167. {
  168. return md.BlobIndexSize();
  169. }
  170. internal sealed override void Write(PEWriter output)
  171. {
  172. //Console.WriteLine("Writing the blob index for a TypeSpec");
  173. output.BlobIndex(sigIx);
  174. }
  175. internal sealed override uint GetCodedIx(CIx code)
  176. {
  177. switch (code)
  178. {
  179. case (CIx.TypeDefOrRef): return 2;
  180. case (CIx.HasCustomAttr): return 13;
  181. case (CIx.MemberRefParent): return 4;
  182. }
  183. return 0;
  184. }
  185. }
  186. /**************************************************************************/
  187. /// <summary>
  188. /// Descriptor for the Primitive types defined in IL
  189. /// </summary>
  190. public class PrimitiveType : TypeSpec
  191. {
  192. private string name;
  193. private int systemTypeIndex;
  194. internal static int NumSystemTypes = 18;
  195. public static readonly PrimitiveType Void = new PrimitiveType(0x01, "Void", 0);
  196. public static readonly PrimitiveType Boolean = new PrimitiveType(0x02, "Boolean", 1);
  197. public static readonly PrimitiveType Char = new PrimitiveType(0x03, "Char", 2);
  198. public static readonly PrimitiveType Int8 = new PrimitiveType(0x04, "SByte", 3);
  199. public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05, "Byte", 4);
  200. public static readonly PrimitiveType Int16 = new PrimitiveType(0x06, "Int16", 5);
  201. public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07, "UInt16", 6);
  202. public static readonly PrimitiveType Int32 = new PrimitiveType(0x08, "Int32", 7);
  203. public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09, "UInt32", 8);
  204. public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A, "Int64", 9);
  205. public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B, "UInt64", 10);
  206. public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C, "Single", 11);
  207. public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D, "Double", 12);
  208. public static readonly PrimitiveType String = new PrimitiveType(0x0E, "String", 13);
  209. internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
  210. public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16, "TypedReference", 14);
  211. public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18, "IntPtr", 15);
  212. public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19, "UIntPtr", 16);
  213. public static readonly PrimitiveType Object = new PrimitiveType(0x1C, "Object", 17);
  214. internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
  215. internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
  216. public static readonly PrimitiveType NativeInt = IntPtr;
  217. public static readonly PrimitiveType NativeUInt = UIntPtr;
  218. internal static PrimitiveType[] primitives = {null,Void,Boolean,Char,Int8,UInt8,
  219. Int16,UInt16,Int32,UInt32,Int64,
  220. UInt64,Float32,Float64,String};
  221. /*-------------------- Constructors ---------------------------------*/
  222. internal PrimitiveType(byte typeIx) : base(typeIx) { }
  223. internal PrimitiveType(byte typeIx, string name, int STIx)
  224. : base(typeIx)
  225. {
  226. this.name = name;
  227. this.systemTypeIndex = STIx;
  228. }
  229. internal string GetName() { return name; }
  230. public override string TypeName()
  231. {
  232. if (typeIndex == 0x0E) return "System.String";
  233. return name;
  234. }
  235. internal int GetSystemTypeIx() { return systemTypeIndex; }
  236. internal sealed override void TypeSig(MemoryStream str)
  237. {
  238. str.WriteByte(typeIndex);
  239. }
  240. internal override void WriteType(CILWriter output)
  241. {
  242. //if (typeIndex == 0x0E) {
  243. // output.Write("[mscorlib]System.String");
  244. //} else
  245. switch (typeIndex)
  246. {
  247. case (0x1C): output.Write("[mscorlib]System.Object"); break;
  248. case (0x02): output.Write("bool"); break;
  249. case (0x0C): output.Write("float32"); break;
  250. case (0x0D): output.Write("float64"); break;
  251. default: output.Write(name.ToLower()); break;
  252. }
  253. }
  254. internal sealed override bool SameType(Type tstType)
  255. {
  256. if (tstType is SystemClass)
  257. return tstType.SameType(this);
  258. return this == tstType;
  259. }
  260. /* now done in MetaDataOut.WriteTildeStream
  261. internal static void ClearAddedFlags() { // KJG 18-April-2005
  262. for (int i = 0; i < primitives.Length; i++) {
  263. if (primitives[i] != null) primitives[i].typeSpecAdded = false;
  264. }
  265. }
  266. */
  267. }
  268. /**************************************************************************/
  269. /// <summary>
  270. /// Descriptor for a generic parameter for either a class or method.
  271. /// </summary>
  272. public class GenericParam : Type
  273. {
  274. private static readonly byte VAR = 0x13;
  275. private static readonly byte MVAR = 0x1E;
  276. ushort flags, index, kind = 0;
  277. uint parentIx, nameIx;
  278. string name;
  279. MetaDataElement parent;
  280. // Users add and remove constraintTypes to this list.
  281. // The constraints list is used during metadata output
  282. // and contains objects of GenericParamConstraint type.
  283. private List<Type> constraintTypes = new List<Type>();
  284. private List<GenericParamConstraint> constraints = new List<GenericParamConstraint>();
  285. internal static bool extraField = true;
  286. // There should only be one GenericParTypeSpec entry
  287. // int the metadata for each GenericParam.
  288. GenericParTypeSpec myTypeSpec;
  289. /*-------------------- Constructors ---------------------------------*/
  290. private GenericParam(uint index, byte elemIx)
  291. : base(elemIx)
  292. {
  293. this.index = (ushort)index;
  294. sortTable = true;
  295. }
  296. internal GenericParam(string name, MetaDataElement parent, int index)
  297. : base(VAR)
  298. {
  299. this.name = name;
  300. this.parent = parent;
  301. this.index = (ushort)index;
  302. if (parent is Method) typeIndex = MVAR;
  303. sortTable = true;
  304. tabIx = MDTable.GenericParam;
  305. }
  306. internal GenericParam(PEReader buff)
  307. : base(VAR)
  308. {
  309. index = buff.ReadUInt16();
  310. flags = buff.ReadUInt16();
  311. parentIx = buff.GetCodedIndex(CIx.TypeOrMethodDef);
  312. name = buff.GetString();
  313. if (extraField) kind = buff.ReadUInt16();
  314. sortTable = true;
  315. tabIx = MDTable.GenericParam;
  316. // resolve generic param immediately for signature resolution
  317. parent = buff.GetCodedElement(CIx.TypeOrMethodDef, parentIx);
  318. if (parent != null)
  319. {
  320. if (parent is MethodDef)
  321. {
  322. typeIndex = MVAR;
  323. ((MethodDef)parent).AddGenericParam(this);
  324. }
  325. else
  326. {
  327. ((ClassDef)parent).AddGenericParam(this);
  328. }
  329. }
  330. }
  331. internal GenericParam(string name)
  332. : base(MVAR)
  333. {
  334. this.name = name;
  335. sortTable = true;
  336. tabIx = MDTable.GenericParam;
  337. }
  338. internal static GenericParam AnonMethPar(uint ix)
  339. {
  340. return new GenericParam(ix, MVAR);
  341. }
  342. internal static GenericParam AnonClassPar(uint ix)
  343. {
  344. return new GenericParam(ix, VAR);
  345. }
  346. internal static void Read(PEReader buff, TableRow[] gpars)
  347. {
  348. for (int i = 0; i < gpars.Length; i++)
  349. gpars[i] = new GenericParam(buff);
  350. }
  351. /*------------------------- public set and get methods --------------------------*/
  352. /// <summary>
  353. /// Set the attribute for this generic parameter
  354. /// </summary>
  355. /// <param name="attr">the attribute</param>
  356. public void SetAttribute(GenericParamAttr attr)
  357. {
  358. flags = (ushort)attr;
  359. }
  360. /// <summary>
  361. /// Get the attribute for this generic parameter
  362. /// </summary>
  363. public GenericParamAttr GetAttribute()
  364. {
  365. return (GenericParamAttr)flags;
  366. }
  367. /// <summary>
  368. /// Add a type constraint to this generic parameter
  369. /// </summary>
  370. /// <param name="cType">type constraining the parameter type</param>
  371. public void AddConstraint(Type cType)
  372. {
  373. constraintTypes.Add(cType);
  374. }
  375. /// <summary>
  376. /// Remove a constraint from this generic parameter
  377. /// </summary>
  378. /// <param name="cType">class type of constraint</param>
  379. public void RemoveConstraint(Type cType)
  380. {
  381. for (int i = 0; i < constraintTypes.Count; i++)
  382. {
  383. if (constraintTypes[i] == cType)
  384. {
  385. constraintTypes.RemoveAt(i);
  386. return;
  387. }
  388. }
  389. }
  390. /// <summary>
  391. /// Return a constraint from the list
  392. /// </summary>
  393. /// <param name="i">constraint index</param>
  394. /// <returns></returns>
  395. public Type GetConstraint(int i)
  396. {
  397. return (Class)constraintTypes[i];
  398. }
  399. /// <summary>
  400. /// Get the number of constrains on this GenericParam
  401. /// </summary>
  402. /// <returns></returns>
  403. public int GetConstraintCount()
  404. {
  405. return constraintTypes.Count;
  406. }
  407. /// <summary>
  408. /// Get the name of this generic parameter
  409. /// </summary>
  410. /// <returns>generic parameter name</returns>
  411. public string GetName() { return name; }
  412. public MetaDataElement GetParent() { return parent; }
  413. public Type[] GetClassConstraints()
  414. {
  415. return constraintTypes.ToArray();
  416. }
  417. /*----------------------------- internal functions ------------------------------*/
  418. internal uint Index
  419. {
  420. get { return index; }
  421. set { index = (ushort)value; }
  422. }
  423. internal void SetClassParam(Class paren, int ix)
  424. {
  425. typeIndex = VAR;
  426. parent = paren;
  427. index = (ushort)ix;
  428. }
  429. internal void SetMethParam(Method paren, int ix)
  430. {
  431. typeIndex = MVAR;
  432. parent = paren;
  433. index = (ushort)ix;
  434. }
  435. internal void CheckParent(MethodDef paren, PEReader buff)
  436. {
  437. if (paren == buff.GetCodedElement(CIx.TypeOrMethodDef, parentIx))
  438. {
  439. parent = paren;
  440. paren.InsertGenericParam(this);
  441. }
  442. }
  443. internal override void TypeSig(MemoryStream str)
  444. {
  445. str.WriteByte(typeIndex);
  446. str.WriteByte((byte)index);
  447. }
  448. internal static uint Size(MetaData md)
  449. {
  450. if (extraField)
  451. return 6 + md.CodedIndexSize(CIx.TypeOrMethodDef) + md.StringsIndexSize();
  452. else
  453. return 4 + md.CodedIndexSize(CIx.TypeOrMethodDef) + md.StringsIndexSize();
  454. }
  455. internal override Type AddTypeSpec(MetaDataOut md)
  456. {
  457. if (this.myTypeSpec == null) {
  458. this.myTypeSpec = new GenericParTypeSpec(this);
  459. md.AddToTable(MDTable.TypeSpec, this.myTypeSpec);
  460. }
  461. return this.myTypeSpec;
  462. }
  463. internal override uint SortKey()
  464. {
  465. return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
  466. | parent.GetCodedIx(CIx.TypeOrMethodDef);
  467. }
  468. internal override void BuildTables(MetaDataOut md) {
  469. if (parent is MethodRef || parent is ClassRef) return; // don't add it - fix by CK
  470. md.AddToTable(MDTable.GenericParam, this);
  471. nameIx = md.AddToStringsHeap(name);
  472. // KJG note, Aug 2010.
  473. // The constraint metadata table (0x2c) holds four kinds of thing:
  474. // (1) TypeDef objects -- always already in table 0x2
  475. // (2) TypeRef objects -- must be entered in table 0x1
  476. // (3) ClassSpec objects -- entered in typespec table 0x1b
  477. // (4) GenericParamTypeSpec objects -- also in table 0x1b.
  478. // These are generated on demand, for those GenericParam
  479. // objects which do not have a TypeSpec already.
  480. // In the last three cases, 2 - 4, the objects should also
  481. // be offered up to the relevant metadata table.
  482. for (int i = 0; i < constraintTypes.Count; i++) {
  483. ClassSpec constraintSpec;
  484. GenericParam constraintParam;
  485. Type cType = constraintTypes[i];
  486. if (cType is ClassRef)
  487. cType.BuildMDTables(md);
  488. else if ((constraintSpec = cType as ClassSpec) != null) {
  489. // Fix by CK - should be BuildTables too??
  490. // Yes it should (kjg) Aug 2010
  491. md.ConditionalAddTypeSpec(cType);
  492. cType.BuildMDTables(md); // Just in case genClass is a TypeRef
  493. }
  494. else if ((constraintParam = cType as GenericParam) != null)
  495. // AddTypeSpec creates GenericParamTypeSpec object and
  496. // adds it to table 0x1b, if not already allocated.
  497. // Replace GenericParam constraint on list by
  498. // the GenericParamTypeSpec
  499. cType = constraintParam.AddTypeSpec(md);
  500. constraints.Add(new GenericParamConstraint(this, cType));
  501. }
  502. }
  503. internal override void BuildCILInfo(CILWriter output)
  504. {
  505. for (int i = 0; i < constraintTypes.Count; i++)
  506. {
  507. Class cClass = (Class)constraintTypes[i];
  508. if (!cClass.isDef())
  509. {
  510. cClass.BuildCILInfo(output);
  511. }
  512. }
  513. }
  514. internal void AddConstraints(MetaDataOut md)
  515. {
  516. for (int i = 0; i < constraints.Count; i++)
  517. {
  518. md.AddToTable(MDTable.GenericParamConstraint, constraints[i]);
  519. }
  520. }
  521. internal override void Write(PEWriter output)
  522. {
  523. output.Write(index);
  524. output.Write(flags);
  525. output.WriteCodedIndex(CIx.TypeOrMethodDef, parent);
  526. output.StringsIndex(nameIx);
  527. if (extraField) output.Write(kind);
  528. }
  529. }
  530. /**************************************************************************/
  531. internal class UnresolvedTypeSpec : TypeSpec
  532. {
  533. uint blobIx;
  534. internal UnresolvedTypeSpec(PEReader buff, int i)
  535. : base(0)
  536. {
  537. blobIx = buff.GetBlobIx();
  538. Row = (uint)i + 1;
  539. this.unresolved = true;
  540. }
  541. internal override void Resolve(PEReader buff)
  542. {
  543. buff.InsertInTable(MDTable.TypeSpec, Row, buff.GetBlobType(blobIx));
  544. this.unresolved = false;
  545. }
  546. }
  547. /**************************************************************************/
  548. /// <summary>
  549. /// Wrapper for Generic Parameter of TypeSpec type.
  550. /// </summary>
  551. public class GenericParTypeSpec : TypeSpec
  552. {
  553. GenericParam gPar;
  554. bool isClassPar;
  555. uint index;
  556. internal GenericParTypeSpec(GenericParam gPar)
  557. : base(gPar.GetTypeIndex())
  558. {
  559. this.gPar = gPar;
  560. }
  561. internal GenericParTypeSpec(int gpTypeIx, uint ix)
  562. : base((byte)gpTypeIx)
  563. {
  564. isClassPar = gpTypeIx == (int)ElementType.Var;
  565. index = ix;
  566. }
  567. internal GenericParam GetGenericParam(MethodDef meth)
  568. {
  569. if (gPar == null)
  570. {
  571. if (isClassPar)
  572. {
  573. ClassDef methClass = (ClassDef)meth.GetParent();
  574. gPar = methClass.GetGenericParam((int)index);
  575. }
  576. else
  577. {
  578. gPar = meth.GetGenericParam((int)index);
  579. }
  580. }
  581. return gPar;
  582. }
  583. internal override void TypeSig(MemoryStream str)
  584. {
  585. gPar.TypeSig(str);
  586. }
  587. }
  588. /**************************************************************************/
  589. /// <summary>
  590. /// The IL Array type: there are two sub-classes --
  591. /// BoundArrays, possibly multi dimensional arrays with bounds.
  592. /// ZeroBasedArrays, built-in 1-D arrays of the CLR
  593. /// </summary>
  594. public abstract class Array : TypeSpec
  595. {
  596. /// <summary>
  597. /// The element type of the array
  598. /// </summary>
  599. protected Type elemType;
  600. /*-------------------- Constructors ---------------------------------*/
  601. internal Array(Type eType, byte TypeId)
  602. : base(TypeId)
  603. {
  604. elemType = eType;
  605. tabIx = MDTable.TypeSpec;
  606. }
  607. public Type ElemType() { return elemType; }
  608. internal sealed override void BuildTables(MetaDataOut md)
  609. {
  610. if (!(elemType is ClassDef))
  611. elemType.BuildMDTables(md);
  612. }
  613. internal sealed override void BuildCILInfo(CILWriter output)
  614. {
  615. if (!(elemType is ClassDef))
  616. elemType.BuildCILInfo(output);
  617. }
  618. }
  619. /**************************************************************************/
  620. /// <summary>
  621. /// Arrays with one or more dimensions, with explicit bounds
  622. /// </summary>
  623. public class BoundArray : Array
  624. {
  625. int[] lowerBounds;
  626. int[] sizes;
  627. uint numDims;
  628. /*-------------------- Constructors ---------------------------------*/
  629. /// <summary>
  630. /// Create a new multi dimensional array type
  631. /// eg. elemType[1..5,3..10,5,,] would be
  632. /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
  633. /// </summary>
  634. /// <param name="elementType">the type of the elements</param>
  635. /// <param name="dimensions">the number of dimensions</param>
  636. /// <param name="loBounds">lower bounds of dimensions</param>
  637. /// <param name="upBounds">upper bounds of dimensions</param>
  638. public BoundArray(
  639. Type elementType,
  640. int dimensions,
  641. int[] loBounds,
  642. int[] upBounds) : base(elementType, 0x14)
  643. {
  644. numDims = (uint)dimensions;
  645. lowerBounds = loBounds;
  646. if (loBounds.Length > dimensions)
  647. throw new TypeSignatureException("Array cannot have more bounds than rank");
  648. if (upBounds != null)
  649. {
  650. if (upBounds.Length > loBounds.Length)
  651. throw new TypeSignatureException("Array cannot have more upper than lower bounds");
  652. sizes = new int[upBounds.Length];
  653. for (int i = 0; i < upBounds.Length; i++)
  654. {
  655. sizes[i] = upBounds[i] - loBounds[i] + 1;
  656. }
  657. }
  658. }
  659. /// <summary>
  660. /// Create a new multi dimensional array type with low bounds
  661. /// specified but no sizes specified. C# arrays T[,] do this
  662. /// with implicit low bounds of zero, but no sizes
  663. /// </summary>
  664. /// <param name="elementType">the type of the elements</param>
  665. /// <param name="dimensions">the number of dimensions</param>
  666. /// <param name="bounds">the low bounds of the dimensions</param>
  667. public BoundArray(Type elementType, int dimensions, int[] bounds)
  668. : base(elementType, 0x14)
  669. {
  670. if (bounds.Length > dimensions)
  671. throw new TypeSignatureException("Array cannot have more bounds than rank");
  672. numDims = (uint)dimensions;
  673. lowerBounds = bounds;
  674. }
  675. /// <summary>
  676. /// Create a new multi dimensional array type
  677. /// eg. elemType[,,] would be new BoundArray(elemType,3)
  678. /// </summary>
  679. /// <param name="elementType">the type of the elements</param>
  680. /// <param name="dimensions">the number of dimensions</param>
  681. public BoundArray(Type elementType, int dimensions)
  682. : base(elementType, 0x14)
  683. {
  684. numDims = (uint)dimensions;
  685. }
  686. internal override bool SameType(Type tstType)
  687. {
  688. if (this == tstType) return true;
  689. if (!(tstType is BoundArray)) return false;
  690. BoundArray bArray = (BoundArray)tstType;
  691. if (elemType.SameType(bArray.ElemType()))
  692. return SameBounds(numDims, lowerBounds, sizes);
  693. return false;
  694. }
  695. internal bool SameBounds(uint dims, int[] lbounds, int[] sizs)
  696. {
  697. if (dims != numDims) return false;
  698. if (lowerBounds != null)
  699. {
  700. if ((lbounds == null) || (lowerBounds.Length != lbounds.Length)) return false;
  701. for (int i = 0; i < lowerBounds.Length; i++)
  702. if (lowerBounds[i] != lbounds[i]) return false;
  703. }
  704. else
  705. if (lbounds != null) return false;
  706. if (sizes != null)
  707. {
  708. if ((sizs == null) || (sizes.Length != sizs.Length)) return false;
  709. for (int i = 0; i < sizes.Length; i++)
  710. if (sizes[i] != sizs[i]) return false;
  711. }
  712. else
  713. if (sizs != null) return false;
  714. return true;
  715. }
  716. internal sealed override void TypeSig(MemoryStream str)
  717. {
  718. str.WriteByte(typeIndex);
  719. elemType.TypeSig(str);
  720. MetaDataOut.CompressNum(BlobUtil.CompressUInt(numDims), str);
  721. if ((sizes != null) && (sizes.Length > 0))
  722. {
  723. MetaDataOut.CompressNum(BlobUtil.CompressUInt((uint)sizes.Length), str);
  724. for (int i = 0; i < sizes.Length; i++)
  725. {
  726. MetaDataOut.CompressNum(BlobUtil.CompressUInt((uint)sizes[i]), str);
  727. }
  728. }
  729. else str.WriteByte(0);
  730. if ((lowerBounds != null) && (lowerBounds.Length > 0))
  731. {
  732. MetaDataOut.CompressNum(BlobUtil.CompressUInt((uint)lowerBounds.Length), str);
  733. for (int i = 0; i < lowerBounds.Length; i++)
  734. {
  735. MetaDataOut.CompressNum(BlobUtil.CompressInt(lowerBounds[i]), str);
  736. }
  737. }
  738. else str.WriteByte(0);
  739. }
  740. }
  741. /**************************************************************************/
  742. /// <summary>
  743. /// Single dimensional array with zero lower bound
  744. /// </summary>
  745. public class ZeroBasedArray : Array
  746. {
  747. /*-------------------- Constructors ---------------------------------*/
  748. /// <summary>
  749. /// Create a new array - elementType[]
  750. /// </summary>
  751. /// <param name="elementType">the type of the array elements</param>
  752. public ZeroBasedArray(Type elementType) : base(elementType, (byte)ElementType.SZArray) { }
  753. internal sealed override void TypeSig(MemoryStream str)
  754. {
  755. str.WriteByte(typeIndex);
  756. elemType.TypeSig(str);
  757. }
  758. internal override bool SameType(Type tstType)
  759. {
  760. if (this == tstType) return true;
  761. if (!(tstType is ZeroBasedArray)) return false;
  762. //return elemType == ((ZeroBasedArray)tstType).ElemType();
  763. return elemType.SameType(((ZeroBasedArray)tstType).ElemType());
  764. }
  765. internal override void WriteType(CILWriter output)
  766. {
  767. elemType.WriteType(output);
  768. output.Write("[]");
  769. }
  770. }
  771. /**************************************************************************/
  772. /// <summary>
  773. /// Descriptor for a FunctionPointer type
  774. /// </summary>
  775. ///
  776. public class MethPtrType : TypeSpec
  777. {
  778. // MethPtrType == FNPTR
  779. Method meth;
  780. MethSig mSig;
  781. /*-------------------- Constructors ---------------------------------*/
  782. /// <summary>
  783. /// Create a new function pointer type
  784. /// </summary>
  785. /// <param name="meth">the function to be referenced</param>
  786. public MethPtrType(Method meth)
  787. : base((byte)ElementType.FnPtr)
  788. {
  789. this.meth = meth;
  790. }
  791. internal MethPtrType(MethSig msig)
  792. : base((byte)ElementType.FnPtr)
  793. {
  794. mSig = msig;
  795. }
  796. internal sealed override void TypeSig(MemoryStream str)
  797. {
  798. str.WriteByte(typeIndex);
  799. if (meth == null)
  800. mSig.TypeSig(str);
  801. else
  802. meth.TypeSig(str);
  803. }
  804. internal override bool SameType(Type tstType)
  805. {
  806. if (this == tstType) return true;
  807. if (tstType is MethPtrType)
  808. {
  809. MethPtrType mpType = (MethPtrType)tstType;
  810. }
  811. return false;
  812. }
  813. internal sealed override void BuildTables(MetaDataOut md)
  814. {
  815. Type[] types = meth.GetParTypes();
  816. if (types != null)
  817. for (int i = 0; i < types.Length; i++)
  818. types[i].BuildMDTables(md);
  819. types = meth.GetOptParTypes();
  820. if (types != null)
  821. for (int i = 0; i < types.Length; i++)
  822. types[i].BuildMDTables(md);
  823. }
  824. internal sealed override void BuildCILInfo(CILWriter output)
  825. {
  826. Type[] types = meth.GetParTypes();
  827. if (types != null)
  828. for (int i = 0; i < types.Length; i++)
  829. types[i].BuildCILInfo(output);
  830. types = meth.GetOptParTypes();
  831. if (types != null)
  832. for (int i = 0; i < types.Length; i++)
  833. types[i].BuildCILInfo(output);
  834. }
  835. /* internal sealed override void BuildSignatures(MetaDataOut md) {
  836. if (sigIx == 0) {
  837. MemoryStream sig = new MemoryStream();
  838. TypeSig(sig);
  839. sigIx = md.AddToBlobHeap(sig.ToArray());
  840. }
  841. done = false;
  842. }
  843. */
  844. }
  845. /**************************************************************************/
  846. /// <summary>
  847. /// Descriptor for an pointer (type * or type &)
  848. /// </summary>
  849. public abstract class PtrType : TypeSpec
  850. {
  851. protected Type baseType;
  852. /*-------------------- Constructors ---------------------------------*/
  853. internal PtrType(Type bType, byte typeIx)
  854. : base(typeIx)
  855. {
  856. baseType = bType;
  857. }
  858. public Type GetBaseType() { return baseType; }
  859. internal sealed override void TypeSig(MemoryStream str)
  860. {
  861. str.WriteByte(typeIndex);
  862. baseType.TypeSig(str);
  863. }
  864. internal sealed override void BuildTables(MetaDataOut md)
  865. {
  866. if (!(baseType is ClassDef))
  867. baseType.BuildMDTables(md);
  868. }
  869. internal sealed override void BuildCILInfo(CILWriter output)
  870. {
  871. if (!(baseType is ClassDef))
  872. baseType.BuildCILInfo(output);
  873. }
  874. }
  875. /**************************************************************************/
  876. /// <summary>
  877. /// Descriptor for a managed pointer (type & or byref)
  878. /// </summary>
  879. public class ManagedPointer : PtrType
  880. { // <type> & (BYREF)
  881. /*-------------------- Constructors ---------------------------------*/
  882. /// <summary>
  883. /// Create new managed pointer to baseType
  884. /// </summary>
  885. /// <param name="bType">the base type of the pointer</param>
  886. public ManagedPointer(Type baseType) : base(baseType, 0x10) { }
  887. }
  888. /**************************************************************************/
  889. /// <summary>
  890. /// Descriptor for an unmanaged pointer (type *)
  891. /// </summary>
  892. public class UnmanagedPointer : PtrType
  893. { // PTR
  894. /*-------------------- Constructors ---------------------------------*/
  895. /// <summary>
  896. /// Create a new unmanaged pointer to baseType
  897. /// </summary>
  898. /// <param name="baseType">the base type of the pointer</param>
  899. public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
  900. }
  901. }