2005-08-26 Iain McCoy <iain@mccoy.id.au>
[mono.git] / mcs / ilasm / codegen / ExternTable.cs
1 //
2 // Mono.ILASM.ExternTable.cs
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10 using System;
11 using System.Collections;
12 using System.Reflection;
13
14 namespace Mono.ILASM {
15
16         public abstract class ExternRef : ICustomAttrTarget {
17
18                 protected string name;
19                 protected Hashtable class_table;
20                 protected Hashtable typeref_table;
21                 protected ArrayList customattr_list;
22
23                 public abstract void Resolve (CodeGen codegen);
24                 public abstract PEAPI.IExternRef GetExternRef ();
25
26                 public ExternRef (string name)
27                 {
28                         this.name = name;
29                         typeref_table = new Hashtable ();
30                         class_table = new Hashtable ();
31                 }
32
33                 public string Name {
34                         get { return name; }
35                 }
36
37                 public void AddCustomAttribute (CustomAttr customattr)
38                 {
39                         if (customattr_list == null)
40                                 customattr_list = new ArrayList ();
41
42                         customattr_list.Add (customattr);
43                 }
44
45                 public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype, ExternTable table)
46                 {
47                         ExternTypeRef type_ref = typeref_table [full_name] as ExternTypeRef;
48                         
49                         if (type_ref != null) {
50                                 if (is_valuetype)
51                                         type_ref.MakeValueClass ();
52                                 return type_ref;
53                         }        
54                         
55                         type_ref = new ExternTypeRef (this, full_name, is_valuetype, table);
56                         typeref_table [full_name] = type_ref;
57                         
58                         return type_ref;
59                 }
60
61                 public PEAPI.ClassRef GetType (string full_name)
62                 {
63                         PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
64                         
65                         if (klass != null)
66                                 return klass;
67
68                         string name_space, name;
69                         ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
70
71                         klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
72                         class_table[full_name] = klass;
73
74                         return klass;
75                 }
76
77                 public PEAPI.ClassRef GetValueType (string full_name)
78                 {
79                         PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
80
81                         if (klass != null) 
82                                 return klass;
83
84                         string name_space, name;
85                         ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
86
87                         klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
88                         class_table[full_name] = klass;
89
90                         return klass;
91                 }
92         }
93
94         public class ExternModule : ExternRef {
95
96                 public PEAPI.ModuleRef ModuleRef;
97
98                 public ExternModule (string name) : base (name)
99                 {
100                 }
101
102                 public override void Resolve (CodeGen codegen)
103                 {
104                         ModuleRef = codegen.PEFile.AddExternModule (name);
105                         if (customattr_list != null)
106                                 foreach (CustomAttr customattr in customattr_list)
107                                         customattr.AddTo (codegen, ModuleRef);
108                 }
109
110                 
111                 public override PEAPI.IExternRef GetExternRef ()
112                 {
113                         return ModuleRef;
114                 }
115         }
116
117         public class ExternAssembly : ExternRef, IDeclSecurityTarget {
118                         
119                 public PEAPI.AssemblyRef AssemblyRef;
120
121                 private int major, minor, build, revision;
122                 private byte [] public_key;
123                 private byte [] public_key_token;
124                 private string locale;
125                 private byte [] hash;
126                 private ArrayList declsec_list;
127
128                 public ExternAssembly (string name, AssemblyName asmb_name) : base (name)
129                 {
130                         this.name = name;
131                         major = minor = build = revision = -1;
132                 }
133
134                 public override void Resolve (CodeGen code_gen)
135                 {
136                         AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
137                         if (major != -1)
138                                 AssemblyRef.AddVersionInfo (major, minor, build, revision);
139                         if (public_key != null)
140                                 AssemblyRef.AddKey (public_key);
141                         if (public_key_token != null)
142                                 AssemblyRef.AddKeyToken (public_key_token);
143                         if (locale != null)
144                                 AssemblyRef.AddCulture (locale);
145                         if (hash != null)
146                                 AssemblyRef.AddHash (hash);
147
148                         if (customattr_list != null)
149                                 foreach (CustomAttr customattr in customattr_list)
150                                         customattr.AddTo (code_gen, AssemblyRef);
151                                         
152                         if (declsec_list != null)
153                                 foreach (DeclSecurity decl_sec in declsec_list)
154                                         decl_sec.AddTo (code_gen, AssemblyRef);
155
156                         class_table = new Hashtable ();
157                 }
158
159                 public override PEAPI.IExternRef GetExternRef ()
160                 {
161                         return AssemblyRef;
162                 }
163                 
164                 public void AddDeclSecurity (DeclSecurity decl_sec)
165                 {
166                         if (declsec_list == null)
167                                 declsec_list = new ArrayList ();
168
169                         declsec_list.Add (decl_sec);
170                 }
171
172                 public void SetVersion (int major, int minor, int build, int revision)
173                 {
174                         this.major = major;
175                         this.minor = minor;
176                         this.build = build;
177                         this.revision = revision;
178                 }
179
180                 public void SetPublicKey (byte [] public_key)
181                 {
182                         this.public_key = public_key;
183                 }
184
185                 public void SetPublicKeyToken (byte [] public_key_token)
186                 {
187                         this.public_key_token = public_key_token;
188                 }
189
190                 public void SetLocale (string locale)
191                 {
192                         this.locale = locale;
193                 }
194
195                 public void SetHash (byte [] hash)
196                 {
197                         this.hash = hash;
198                 }
199
200         }
201
202         
203         public class ExternTable {
204
205                 Hashtable assembly_table;
206                 Hashtable module_table;
207                 
208                 public void AddCorlib ()
209                 {
210                         // Add mscorlib
211                         string mscorlib_name = "mscorlib";
212                         AssemblyName mscorlib = new AssemblyName ();
213                         mscorlib.Name = mscorlib_name;
214                         AddAssembly (mscorlib_name, mscorlib);
215
216                         // Also need to alias corlib, normally corlib and
217                         // mscorlib are used interchangably
218                         assembly_table["corlib"] = assembly_table["mscorlib"];
219                 }
220
221                 public ExternAssembly AddAssembly (string name, AssemblyName asmb_name)
222                 {
223                         ExternAssembly ea = null;
224
225                         if (assembly_table == null) {
226                                 assembly_table = new Hashtable ();
227                         } else {
228                                 ea = assembly_table [name] as ExternAssembly;
229                                 if (ea != null)
230                                         return ea;
231                         }
232
233                         ea = new ExternAssembly (name, asmb_name);
234
235                         assembly_table [name] = ea;
236
237                         return ea;
238                 }
239
240                 public ExternModule AddModule (string name)
241                 {
242                         ExternModule em = null;
243
244                         if (module_table == null) {
245                                 module_table = new Hashtable ();
246                         } else {
247                                 em = module_table [name] as ExternModule;
248                                 if (em != null)
249                                         return em;
250                         }
251
252                         em = new ExternModule (name);
253
254                         module_table [name] = em;
255
256                         return em;
257                 }
258
259                 public void Resolve (CodeGen code_gen)
260                 {
261                         if (assembly_table != null)
262                                 foreach (ExternAssembly ext in assembly_table.Values)
263                                         ext.Resolve (code_gen);
264                         if (module_table == null)
265                                 return;
266                         foreach (ExternModule ext in module_table.Values)
267                                 ext.Resolve (code_gen);
268                 }
269
270                 public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
271                 {
272                         ExternAssembly ext_asmb = null;
273                         if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib"))
274                                 /* AddCorlib if mscorlib is being referenced but
275                                    we haven't encountered a ".assembly 'name'" as yet. */
276                                 AddCorlib ();
277                         if (assembly_table != null)
278                                 ext_asmb = assembly_table[asmb_name] as ExternAssembly;
279
280                         if (ext_asmb == null)
281                                 throw new Exception (String.Format ("Assembly {0} not defined.", asmb_name));
282
283                         return ext_asmb.GetTypeRef (full_name, is_valuetype, this);
284                 }
285
286                 public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
287                 {
288                         ExternModule mod;
289                         mod = module_table [mod_name] as ExternModule;
290
291                         if (mod == null)
292                                 throw new Exception (String.Format ("Module {0} not defined.", mod_name));
293
294                         return mod.GetTypeRef (full_name, is_valuetype, this);
295                 }
296
297                 public static void GetNameAndNamespace (string full_name,
298                         out string name_space, out string name) {
299
300                         int last_dot = full_name.LastIndexOf ('.');
301
302                         if (last_dot < 0) {
303                                 name_space = String.Empty;
304                                 name = full_name;
305                                 return;
306                         }
307
308                         name_space = full_name.Substring (0, last_dot);
309                         name = full_name.Substring (last_dot + 1);
310                 }
311
312         }
313 }
314