/Mono.Cecil/TypeSystem.cs
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}