d818d57d0b89c3d880afc6a0fc41344a8646d6c7
[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                                 var types = metadata.Types;
51
52                                 for (int i = 0; i < types.Length; i++) {
53                                         var type = types [i];
54                                         if (type == null)
55                                                 continue;
56
57                                         if (type.Name == name && type.Namespace == @namespace)
58                                                 return type;
59                                 }
60
61                                 return null;
62                         }
63
64                         static void Initialize (object obj)
65                         {
66                         }
67                 }
68
69                 sealed class CommonTypeSystem : TypeSystem {
70
71                         AssemblyNameReference corlib;
72
73                         public CommonTypeSystem (ModuleDefinition module)
74                                 : base (module)
75                         {
76                         }
77
78                         internal override TypeReference LookupType (string @namespace, string name)
79                         {
80                                 return CreateTypeReference (@namespace, name);
81                         }
82
83                         public AssemblyNameReference GetCorlibReference ()
84                         {
85                                 if (corlib != null)
86                                         return corlib;
87
88                                 const string mscorlib = "mscorlib";
89
90                                 var references = module.AssemblyReferences;
91
92                                 for (int i = 0; i < references.Count; i++) {
93                                         var reference = references [i];
94                                         if (reference.Name == mscorlib)
95                                                 return corlib = reference;
96                                 }
97
98                                 corlib = new AssemblyNameReference {
99                                         Name = mscorlib,
100                                         Version = GetCorlibVersion (),
101                                         PublicKeyToken = new byte [] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 },
102                                 };
103
104                                 references.Add (corlib);
105
106                                 return corlib;
107                         }
108
109                         Version GetCorlibVersion ()
110                         {
111                                 switch (module.Runtime) {
112                                 case TargetRuntime.Net_1_0:
113                                 case TargetRuntime.Net_1_1:
114                                         return new Version (1, 0, 0, 0);
115                                 case TargetRuntime.Net_2_0:
116                                         return new Version (2, 0, 0, 0);
117                                 case TargetRuntime.Net_4_0:
118                                         return new Version (4, 0, 0, 0);
119                                 default:
120                                         throw new NotSupportedException ();
121                                 }
122                         }
123
124                         TypeReference CreateTypeReference (string @namespace, string name)
125                         {
126                                 return new TypeReference (@namespace, name, module, GetCorlibReference ());
127                         }
128                 }
129
130                 readonly ModuleDefinition module;
131
132                 TypeReference type_object;
133                 TypeReference type_void;
134                 TypeReference type_bool;
135                 TypeReference type_char;
136                 TypeReference type_sbyte;
137                 TypeReference type_byte;
138                 TypeReference type_int16;
139                 TypeReference type_uint16;
140                 TypeReference type_int32;
141                 TypeReference type_uint32;
142                 TypeReference type_int64;
143                 TypeReference type_uint64;
144                 TypeReference type_single;
145                 TypeReference type_double;
146                 TypeReference type_intptr;
147                 TypeReference type_uintptr;
148                 TypeReference type_string;
149                 TypeReference type_typedref;
150
151                 TypeSystem (ModuleDefinition module)
152                 {
153                         this.module = module;
154                 }
155
156                 internal static TypeSystem CreateTypeSystem (ModuleDefinition module)
157                 {
158                         if (IsCorlib (module))
159                                 return new CorlibTypeSystem (module);
160
161                         return new CommonTypeSystem (module);
162                 }
163
164                 static bool IsCorlib (ModuleDefinition module)
165                 {
166                         if (module.Assembly == null)
167                                 return false;
168
169                         return module.Assembly.Name.Name == "mscorlib";
170                 }
171
172                 internal abstract TypeReference LookupType (string @namespace, string name);
173
174                 TypeReference LookupSystemType (string name, ElementType element_type)
175                 {
176                         var type = LookupType ("System", name);
177                         type.etype = element_type;
178                         return type;
179                 }
180
181                 TypeReference LookupSystemValueType (string name, ElementType element_type)
182                 {
183                         var type = LookupSystemType (name, element_type);
184                         type.IsValueType = true;
185                         return type;
186                 }
187
188                 public IMetadataScope Corlib {
189                         get {
190                                 var common = this as CommonTypeSystem;
191                                 if (common == null)
192                                         return module;
193
194                                 return common.GetCorlibReference ();
195                         }
196                 }
197
198                 public TypeReference Object {
199                         get { return type_object ?? (type_object = LookupSystemType ("Object", ElementType.Object)); }
200                 }
201
202                 public TypeReference Void {
203                         get { return type_void ?? (type_void = LookupSystemType ("Void", ElementType.Void)); }
204                 }
205
206                 public TypeReference Boolean {
207                         get { return type_bool ?? (type_bool = LookupSystemValueType ("Boolean", ElementType.Boolean)); }
208                 }
209
210                 public TypeReference Char {
211                         get { return type_char ?? (type_char = LookupSystemValueType ("Char", ElementType.Char)); }
212                 }
213
214                 public TypeReference SByte {
215                         get { return type_sbyte ?? (type_sbyte = LookupSystemValueType ("SByte", ElementType.I1)); }
216                 }
217
218                 public TypeReference Byte {
219                         get { return type_byte ?? (type_byte = LookupSystemValueType ("Byte", ElementType.U1)); }
220                 }
221
222                 public TypeReference Int16 {
223                         get { return type_int16 ?? (type_int16 = LookupSystemValueType ("Int16", ElementType.I2)); }
224                 }
225
226                 public TypeReference UInt16 {
227                         get { return type_uint16 ?? (type_uint16 = LookupSystemValueType ("UInt16", ElementType.U2)); }
228                 }
229
230                 public TypeReference Int32 {
231                         get { return type_int32 ?? (type_int32 = LookupSystemValueType ("Int32", ElementType.I4)); }
232                 }
233
234                 public TypeReference UInt32 {
235                         get { return type_uint32 ?? (type_uint32 = LookupSystemValueType ("UInt32", ElementType.U4)); }
236                 }
237
238                 public TypeReference Int64 {
239                         get { return type_int64 ?? (type_int64 = LookupSystemValueType ("Int64", ElementType.I8)); }
240                 }
241
242                 public TypeReference UInt64 {
243                         get { return type_uint64 ?? (type_uint64 = LookupSystemValueType ("UInt64", ElementType.U8)); }
244                 }
245
246                 public TypeReference Single {
247                         get { return type_single ?? (type_single = LookupSystemValueType ("Single", ElementType.R4)); }
248                 }
249
250                 public TypeReference Double {
251                         get { return type_double ?? (type_double = LookupSystemValueType ("Double", ElementType.R8)); }
252                 }
253
254                 public TypeReference IntPtr {
255                         get { return type_intptr ?? (type_intptr = LookupSystemValueType ("IntPtr", ElementType.I)); }
256                 }
257
258                 public TypeReference UIntPtr {
259                         get { return type_uintptr ?? (type_uintptr = LookupSystemValueType ("UIntPtr", ElementType.U)); }
260                 }
261
262                 public TypeReference String {
263                         get { return type_string ?? (type_string = LookupSystemType ("String", ElementType.String)); }
264                 }
265
266                 public TypeReference TypedReference {
267                         get { return type_typedref ?? (type_typedref = LookupSystemValueType ("TypedReference", ElementType.TypedByRef)); }
268                 }
269         }
270 }