PageRenderTime 43ms CodeModel.GetById 1ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

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