0b0ba91b9b58ac10bfc8ed97b4328406c8ca2a21
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / TypeSystem.cs
1 //
2 // TypeSystem.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2010 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30
31 using Mono.Cecil.Metadata;
32
33 namespace Mono.Cecil {
34
35         public abstract class TypeSystem {
36
37                 sealed class CorlibTypeSystem : TypeSystem {
38
39                         public CorlibTypeSystem (ModuleDefinition module)
40                                 : base (module)
41                         {
42                         }
43
44                         internal override TypeReference LookupType (string @namespace, string name)
45                         {
46                                 var metadata = module.MetadataSystem;
47                                 if (metadata.Types == null)
48                                         Initialize (module.Types);
49
50                                 return module.Read (this, (_, reader) => {
51                                         var types = reader.metadata.Types;
52
53                                         for (int i = 0; i < types.Length; i++) {
54                                                 if (types [i] == null)
55                                                         types [i] = reader.GetTypeDefinition ((uint) i + 1);
56
57                                                 var type = types [i];
58
59                                                 if (type.Name == name && type.Namespace == @namespace)
60                                                         return type;
61                                         }
62
63                                         return null;
64                                 });
65                         }
66
67                         static void Initialize (object obj)
68                         {
69                         }
70                 }
71
72                 sealed class CommonTypeSystem : TypeSystem {
73
74                         AssemblyNameReference corlib;
75
76                         public CommonTypeSystem (ModuleDefinition module)
77                                 : base (module)
78                         {
79                         }
80
81                         internal override TypeReference LookupType (string @namespace, string name)
82                         {
83                                 return CreateTypeReference (@namespace, name);
84                         }
85
86                         public AssemblyNameReference GetCorlibReference ()
87                         {
88                                 if (corlib != null)
89                                         return corlib;
90
91                                 const string mscorlib = "mscorlib";
92
93                                 var references = module.AssemblyReferences;
94
95                                 for (int i = 0; i < references.Count; i++) {
96                                         var reference = references [i];
97                                         if (reference.Name == mscorlib)
98                                                 return corlib = reference;
99                                 }
100
101                                 corlib = new AssemblyNameReference {
102                                         Name = mscorlib,
103                                         Version = GetCorlibVersion (),
104                                         PublicKeyToken = new byte [] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 },
105                                 };
106
107                                 references.Add (corlib);
108
109                                 return corlib;
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, GetCorlibReference ());
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 (IsCorlib (module))
162                                 return new CorlibTypeSystem (module);
163
164                         return new CommonTypeSystem (module);
165                 }
166
167                 static bool IsCorlib (ModuleDefinition module)
168                 {
169                         if (module.Assembly == null)
170                                 return false;
171
172                         return module.Assembly.Name.Name == "mscorlib";
173                 }
174
175                 internal abstract TypeReference LookupType (string @namespace, string name);
176
177                 TypeReference LookupSystemType (string name, ElementType element_type)
178                 {
179                         var type = LookupType ("System", name);
180                         type.etype = element_type;
181                         return type;
182                 }
183
184                 TypeReference LookupSystemValueType (string name, ElementType element_type)
185                 {
186                         var type = LookupSystemType (name, element_type);
187                         type.IsValueType = true;
188                         return type;
189                 }
190
191                 public IMetadataScope Corlib {
192                         get {
193                                 var common = this as CommonTypeSystem;
194                                 if (common == null)
195                                         return module;
196
197                                 return common.GetCorlibReference ();
198                         }
199                 }
200
201                 public TypeReference Object {
202                         get { return type_object ?? (type_object = LookupSystemType ("Object", ElementType.Object)); }
203                 }
204
205                 public TypeReference Void {
206                         get { return type_void ?? (type_void = LookupSystemType ("Void", ElementType.Void)); }
207                 }
208
209                 public TypeReference Boolean {
210                         get { return type_bool ?? (type_bool = LookupSystemValueType ("Boolean", ElementType.Boolean)); }
211                 }
212
213                 public TypeReference Char {
214                         get { return type_char ?? (type_char = LookupSystemValueType ("Char", ElementType.Char)); }
215                 }
216
217                 public TypeReference SByte {
218                         get { return type_sbyte ?? (type_sbyte = LookupSystemValueType ("SByte", ElementType.I1)); }
219                 }
220
221                 public TypeReference Byte {
222                         get { return type_byte ?? (type_byte = LookupSystemValueType ("Byte", ElementType.U1)); }
223                 }
224
225                 public TypeReference Int16 {
226                         get { return type_int16 ?? (type_int16 = LookupSystemValueType ("Int16", ElementType.I2)); }
227                 }
228
229                 public TypeReference UInt16 {
230                         get { return type_uint16 ?? (type_uint16 = LookupSystemValueType ("UInt16", ElementType.U2)); }
231                 }
232
233                 public TypeReference Int32 {
234                         get { return type_int32 ?? (type_int32 = LookupSystemValueType ("Int32", ElementType.I4)); }
235                 }
236
237                 public TypeReference UInt32 {
238                         get { return type_uint32 ?? (type_uint32 = LookupSystemValueType ("UInt32", ElementType.U4)); }
239                 }
240
241                 public TypeReference Int64 {
242                         get { return type_int64 ?? (type_int64 = LookupSystemValueType ("Int64", ElementType.I8)); }
243                 }
244
245                 public TypeReference UInt64 {
246                         get { return type_uint64 ?? (type_uint64 = LookupSystemValueType ("UInt64", ElementType.U8)); }
247                 }
248
249                 public TypeReference Single {
250                         get { return type_single ?? (type_single = LookupSystemValueType ("Single", ElementType.R4)); }
251                 }
252
253                 public TypeReference Double {
254                         get { return type_double ?? (type_double = LookupSystemValueType ("Double", ElementType.R8)); }
255                 }
256
257                 public TypeReference IntPtr {
258                         get { return type_intptr ?? (type_intptr = LookupSystemValueType ("IntPtr", ElementType.I)); }
259                 }
260
261                 public TypeReference UIntPtr {
262                         get { return type_uintptr ?? (type_uintptr = LookupSystemValueType ("UIntPtr", ElementType.U)); }
263                 }
264
265                 public TypeReference String {
266                         get { return type_string ?? (type_string = LookupSystemType ("String", ElementType.String)); }
267                 }
268
269                 public TypeReference TypedReference {
270                         get { return type_typedref ?? (type_typedref = LookupSystemValueType ("TypedReference", ElementType.TypedByRef)); }
271                 }
272         }
273 }