/Mono.Cecil/TypeSystem.cs

http://github.com/jbevain/cecil · C# · 331 lines · 251 code · 71 blank · 9 comment · 43 complexity · 2882598da22666cab45837daa175f1c2 MD5 · raw file

  1. //
  2. // Author:
  3. // Jb Evain (jbevain@gmail.com)
  4. //
  5. // Copyright (c) 2008 - 2015 Jb Evain
  6. // Copyright (c) 2008 - 2011 Novell, Inc.
  7. //
  8. // Licensed under the MIT/X11 license.
  9. //
  10. using System;
  11. using Mono.Cecil.Metadata;
  12. namespace Mono.Cecil {
  13. public abstract class TypeSystem {
  14. sealed class CoreTypeSystem : TypeSystem {
  15. public CoreTypeSystem (ModuleDefinition module)
  16. : base (module)
  17. {
  18. }
  19. internal override TypeReference LookupType (string @namespace, string name)
  20. {
  21. var type = LookupTypeDefinition (@namespace, name) ?? LookupTypeForwarded (@namespace, name);
  22. if (type != null)
  23. return type;
  24. throw new NotSupportedException ();
  25. }
  26. TypeReference LookupTypeDefinition (string @namespace, string name)
  27. {
  28. var metadata = module.MetadataSystem;
  29. if (metadata.Types == null)
  30. Initialize (module.Types);
  31. return module.Read (new Row<string, string> (@namespace, name), (row, reader) => {
  32. var types = reader.metadata.Types;
  33. for (int i = 0; i < types.Length; i++) {
  34. if (types [i] == null)
  35. types [i] = reader.GetTypeDefinition ((uint) i + 1);
  36. var type = types [i];
  37. if (type.Name == row.Col2 && type.Namespace == row.Col1)
  38. return type;
  39. }
  40. return null;
  41. });
  42. }
  43. TypeReference LookupTypeForwarded (string @namespace, string name)
  44. {
  45. if (!module.HasExportedTypes)
  46. return null;
  47. var exported_types = module.ExportedTypes;
  48. for (int i = 0; i < exported_types.Count; i++) {
  49. var exported_type = exported_types [i];
  50. if (exported_type.Name == name && exported_type.Namespace == @namespace)
  51. return exported_type.CreateReference ();
  52. }
  53. return null;
  54. }
  55. static void Initialize (object obj)
  56. {
  57. }
  58. }
  59. sealed class CommonTypeSystem : TypeSystem {
  60. AssemblyNameReference core_library;
  61. public CommonTypeSystem (ModuleDefinition module)
  62. : base (module)
  63. {
  64. }
  65. internal override TypeReference LookupType (string @namespace, string name)
  66. {
  67. return CreateTypeReference (@namespace, name);
  68. }
  69. public AssemblyNameReference GetCoreLibraryReference ()
  70. {
  71. if (core_library != null)
  72. return core_library;
  73. if (module.TryGetCoreLibraryReference (out core_library))
  74. return core_library;
  75. core_library = new AssemblyNameReference {
  76. Name = Mixin.mscorlib,
  77. Version = GetCorlibVersion (),
  78. PublicKeyToken = new byte [] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 },
  79. };
  80. module.AssemblyReferences.Add (core_library);
  81. return core_library;
  82. }
  83. Version GetCorlibVersion ()
  84. {
  85. switch (module.Runtime) {
  86. case TargetRuntime.Net_1_0:
  87. case TargetRuntime.Net_1_1:
  88. return new Version (1, 0, 0, 0);
  89. case TargetRuntime.Net_2_0:
  90. return new Version (2, 0, 0, 0);
  91. case TargetRuntime.Net_4_0:
  92. return new Version (4, 0, 0, 0);
  93. default:
  94. throw new NotSupportedException ();
  95. }
  96. }
  97. TypeReference CreateTypeReference (string @namespace, string name)
  98. {
  99. return new TypeReference (@namespace, name, module, GetCoreLibraryReference ());
  100. }
  101. }
  102. readonly ModuleDefinition module;
  103. TypeReference type_object;
  104. TypeReference type_void;
  105. TypeReference type_bool;
  106. TypeReference type_char;
  107. TypeReference type_sbyte;
  108. TypeReference type_byte;
  109. TypeReference type_int16;
  110. TypeReference type_uint16;
  111. TypeReference type_int32;
  112. TypeReference type_uint32;
  113. TypeReference type_int64;
  114. TypeReference type_uint64;
  115. TypeReference type_single;
  116. TypeReference type_double;
  117. TypeReference type_intptr;
  118. TypeReference type_uintptr;
  119. TypeReference type_string;
  120. TypeReference type_typedref;
  121. TypeSystem (ModuleDefinition module)
  122. {
  123. this.module = module;
  124. }
  125. internal static TypeSystem CreateTypeSystem (ModuleDefinition module)
  126. {
  127. if (module.IsCoreLibrary ())
  128. return new CoreTypeSystem (module);
  129. return new CommonTypeSystem (module);
  130. }
  131. internal abstract TypeReference LookupType (string @namespace, string name);
  132. TypeReference LookupSystemType (ref TypeReference reference, string name, ElementType element_type)
  133. {
  134. lock (module.SyncRoot) {
  135. if (reference != null)
  136. return reference;
  137. var type = LookupType ("System", name);
  138. type.etype = element_type;
  139. return reference = type;
  140. }
  141. }
  142. TypeReference LookupSystemValueType (ref TypeReference typeRef, string name, ElementType element_type)
  143. {
  144. lock (module.SyncRoot) {
  145. if (typeRef != null)
  146. return typeRef;
  147. var type = LookupType ("System", name);
  148. type.etype = element_type;
  149. type.KnownValueType ();
  150. return typeRef = type;
  151. }
  152. }
  153. [Obsolete ("Use CoreLibrary")]
  154. public IMetadataScope Corlib {
  155. get { return CoreLibrary; }
  156. }
  157. public IMetadataScope CoreLibrary {
  158. get {
  159. var common = this as CommonTypeSystem;
  160. if (common == null)
  161. return module;
  162. return common.GetCoreLibraryReference ();
  163. }
  164. }
  165. public TypeReference Object {
  166. get { return type_object ?? (LookupSystemType (ref type_object, "Object", ElementType.Object)); }
  167. }
  168. public TypeReference Void {
  169. get { return type_void ?? (LookupSystemType (ref type_void, "Void", ElementType.Void)); }
  170. }
  171. public TypeReference Boolean {
  172. get { return type_bool ?? (LookupSystemValueType (ref type_bool, "Boolean", ElementType.Boolean)); }
  173. }
  174. public TypeReference Char {
  175. get { return type_char ?? (LookupSystemValueType (ref type_char, "Char", ElementType.Char)); }
  176. }
  177. public TypeReference SByte {
  178. get { return type_sbyte ?? (LookupSystemValueType (ref type_sbyte, "SByte", ElementType.I1)); }
  179. }
  180. public TypeReference Byte {
  181. get { return type_byte ?? (LookupSystemValueType (ref type_byte, "Byte", ElementType.U1)); }
  182. }
  183. public TypeReference Int16 {
  184. get { return type_int16 ?? (LookupSystemValueType (ref type_int16, "Int16", ElementType.I2)); }
  185. }
  186. public TypeReference UInt16 {
  187. get { return type_uint16 ?? (LookupSystemValueType (ref type_uint16, "UInt16", ElementType.U2)); }
  188. }
  189. public TypeReference Int32 {
  190. get { return type_int32 ?? (LookupSystemValueType (ref type_int32, "Int32", ElementType.I4)); }
  191. }
  192. public TypeReference UInt32 {
  193. get { return type_uint32 ?? (LookupSystemValueType (ref type_uint32, "UInt32", ElementType.U4)); }
  194. }
  195. public TypeReference Int64 {
  196. get { return type_int64 ?? (LookupSystemValueType (ref type_int64, "Int64", ElementType.I8)); }
  197. }
  198. public TypeReference UInt64 {
  199. get { return type_uint64 ?? (LookupSystemValueType (ref type_uint64, "UInt64", ElementType.U8)); }
  200. }
  201. public TypeReference Single {
  202. get { return type_single ?? (LookupSystemValueType (ref type_single, "Single", ElementType.R4)); }
  203. }
  204. public TypeReference Double {
  205. get { return type_double ?? (LookupSystemValueType (ref type_double, "Double", ElementType.R8)); }
  206. }
  207. public TypeReference IntPtr {
  208. get { return type_intptr ?? (LookupSystemValueType (ref type_intptr, "IntPtr", ElementType.I)); }
  209. }
  210. public TypeReference UIntPtr {
  211. get { return type_uintptr ?? (LookupSystemValueType (ref type_uintptr, "UIntPtr", ElementType.U)); }
  212. }
  213. public TypeReference String {
  214. get { return type_string ?? (LookupSystemType (ref type_string, "String", ElementType.String)); }
  215. }
  216. public TypeReference TypedReference {
  217. get { return type_typedref ?? (LookupSystemValueType (ref type_typedref, "TypedReference", ElementType.TypedByRef)); }
  218. }
  219. }
  220. static partial class Mixin {
  221. public const string mscorlib = "mscorlib";
  222. public const string system_runtime = "System.Runtime";
  223. public const string system_private_corelib = "System.Private.CoreLib";
  224. public const string netstandard = "netstandard";
  225. public static bool TryGetCoreLibraryReference (this ModuleDefinition module, out AssemblyNameReference reference)
  226. {
  227. var references = module.AssemblyReferences;
  228. for (int i = 0; i < references.Count; i++) {
  229. reference = references [i];
  230. if (IsCoreLibrary (reference))
  231. return true;
  232. }
  233. reference = null;
  234. return false;
  235. }
  236. public static bool IsCoreLibrary (this ModuleDefinition module)
  237. {
  238. if (module.Assembly == null)
  239. return false;
  240. if (!IsCoreLibrary (module.Assembly.Name))
  241. return false;
  242. if (module.HasImage && module.Read (module, (m, reader) => reader.image.GetTableLength (Table.AssemblyRef) > 0))
  243. return false;
  244. return true;
  245. }
  246. public static void KnownValueType (this TypeReference type)
  247. {
  248. if (!type.IsDefinition)
  249. type.IsValueType = true;
  250. }
  251. static bool IsCoreLibrary (AssemblyNameReference reference)
  252. {
  253. var name = reference.Name;
  254. return name == mscorlib
  255. || name == system_runtime
  256. || name == system_private_corelib
  257. || name == netstandard;
  258. }
  259. }
  260. }