merge -r 58784:58785
[mono.git] / mcs / ilasm / codegen / TypeDef.cs
1 //
2 // Mono.ILASM.TypeDef
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10
11 using System;
12 using System.Collections;
13 using System.Security;
14
15 namespace Mono.ILASM {
16
17         public class TypeDef : ICustomAttrTarget, IDeclSecurityTarget {
18
19                 protected class GenericInfo {
20                         public string Id;
21                         public ArrayList ConstraintList;
22                 }
23
24                 private PEAPI.TypeAttr attr;
25                 private string name_space;
26                 private string name;
27                 private bool is_defined;
28                 private bool is_intransit;
29                 private IClassRef parent;
30                 private ArrayList impl_list;
31                 private PEAPI.ClassDef classdef;
32                 private Hashtable field_table;
33                 private ArrayList field_list;
34                 private Hashtable method_table;
35                 private ArrayList customattr_list;
36                 private DeclSecurity decl_sec;
37                 private ArrayList event_list;
38                 private ArrayList property_list;
39                 private ArrayList typar_list;
40                 private ArrayList override_list;
41                 private ArrayList override_long_list;
42                 private TypeDef outer;
43
44                 private EventDef current_event;
45                 private PropertyDef current_property;
46
47                 private int size;
48                 private int pack;
49
50                 private bool is_value_class;
51                 private bool is_enum_class;
52
53                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
54                                 IClassRef parent, ArrayList impl_list, Location location)
55                 {
56                         this.attr = attr;
57                         this.name_space = name_space;
58                         this.name = name;
59                         this.parent = parent;
60                         this.impl_list = impl_list;
61
62                         field_table = new Hashtable ();
63                         field_list = new ArrayList ();
64
65                         method_table = new Hashtable ();
66
67                         size = -1;
68                         pack = -1;
69
70                         is_defined = false;
71                         is_intransit = false;
72
73                         is_value_class = false;
74                         is_enum_class = false;
75                 }
76
77                 public string Name {
78                         get { return name; }
79                 }
80
81                 public string FullName {
82                         get { return MakeFullName (); }
83                 }
84
85                 public TypeDef OuterType {
86                         get { return outer; }
87                         set { outer = value; }
88                 }
89
90                 public PEAPI.ClassDef PeapiType {
91                         get { return classdef; }
92                 }
93
94                 public PEAPI.ClassDef ClassDef {
95                         get { return classdef; }
96                 }
97
98                 public bool IsGenericType {
99                         get { return (typar_list == null); }
100                 }
101
102                 public bool IsDefined {
103                         get { return is_defined; }
104                 }
105
106                 public EventDef CurrentEvent {
107                         get { return current_event; }
108                 }
109
110                 public PropertyDef CurrentProperty {
111                         get { return current_property; }
112                 }
113
114                 public bool IsInterface {
115                         get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
116                 }
117
118                 public void AddOverride (MethodDef body, ITypeRef parent, string name)
119                 {
120                         if (override_list == null)
121                                 override_list = new ArrayList ();
122                         override_list.Add (new DictionaryEntry (body,
123                                            new DictionaryEntry (parent, name)));
124                 }
125
126                 public void AddOverride (string sig, IMethodRef decl)
127                 {
128                         if (override_long_list == null)
129                                 override_long_list = new ArrayList ();
130                         override_long_list.Add (new DictionaryEntry (sig,
131                                                                 decl));
132                 }
133
134                 public void MakeValueClass ()
135                 {
136                         is_value_class = true;
137                 }
138
139                 public void MakeEnumClass ()
140                 {
141                         is_enum_class = true;
142                 }
143
144                 public void SetSize (int size)
145                 {
146                         this.size = size;
147                 }
148
149                 public void SetPack (int pack)
150                 {
151                         this.pack = pack;
152                 }
153
154                 public void AddFieldDef (FieldDef fielddef)
155                 {
156                         if (IsInterface && !fielddef.IsStatic) {
157                                 Console.WriteLine ("warning -- Non-static field in interface, set to such");
158                                 fielddef.Attributes |= PEAPI.FieldAttr.Static;
159                         }
160
161                         field_table.Add (fielddef.Name, fielddef);
162                         field_list.Add (fielddef);
163                 }
164
165                 public void AddMethodDef (MethodDef methoddef)
166                 {
167                         if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
168                                 Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
169                                 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
170                         }
171
172                         method_table.Add (methoddef.Signature, methoddef);
173                 }
174
175                 public void BeginEventDef (EventDef event_def)
176                 {
177                         if (current_event != null)
178                                 throw new Exception ("An event definition was not closed.");
179
180                         current_event = event_def;
181                 }
182
183                 public void EndEventDef ()
184                 {
185                         if (event_list == null)
186                                 event_list = new ArrayList ();
187
188                         event_list.Add (current_event);
189                         current_event = null;
190                 }
191
192                 public void BeginPropertyDef (PropertyDef property_def)
193                 {
194                         if (current_property != null)
195                                 throw new Exception ("A property definition was not closed.");
196
197                         current_property = property_def;
198                 }
199
200                 public void EndPropertyDef ()
201                 {
202                         if (property_list == null)
203                                 property_list = new ArrayList ();
204
205                         property_list.Add (current_property);
206                         current_property = null;
207                 }
208
209                 public void AddCustomAttribute (CustomAttr customattr)
210                 {
211                         if (customattr_list == null)
212                                 customattr_list = new ArrayList ();
213
214                         customattr_list.Add (customattr);
215                 }
216
217                 public void AddPermissionSet (PEAPI.SecurityAction sec_action, PermissionSet ps)
218                 {
219                         if (decl_sec == null)
220                                 decl_sec = new DeclSecurity ();
221
222                         decl_sec.AddPermissionSet (sec_action, ps);
223                 }
224
225                 public void AddPermission (PEAPI.SecurityAction sec_action, IPermission iper)
226                 {
227                         if (decl_sec == null)
228                                 decl_sec = new DeclSecurity ();
229
230                         decl_sec.AddPermission (sec_action, iper);
231                 }
232
233                 public void AddGenericParam (string id)
234                 {
235                         if (typar_list == null)
236                                 typar_list = new ArrayList ();
237
238                         GenericInfo gi = new GenericInfo ();
239                         gi.Id = id;
240
241                         typar_list.Add (gi);
242                 }
243
244                 public void AddGenericConstraint (int index, ITypeRef constraint)
245                 {
246                         GenericInfo gi = (GenericInfo) typar_list[index];
247
248                         if (gi.ConstraintList == null)
249                                 gi.ConstraintList = new ArrayList ();
250                         gi.ConstraintList.Add (constraint);
251                 }
252
253                 public void Define (CodeGen code_gen)
254                 {
255                         if (is_defined)
256                                 return;
257
258                         if (is_intransit) {
259                                 // Circular definition
260                                 throw new Exception ("Circular definition of class: " + FullName);
261                         }
262
263                         if (parent != null) {
264                                 is_intransit = true;
265                                 parent.Resolve (code_gen);
266                                 is_intransit = false;
267                                 if (parent.PeapiClass == null) {
268                                         throw new Exception ("this type can not be a base type: "
269                                                         + parent);
270                                 }
271
272                                 if (parent.PeapiClass.nameSpace != null && 
273                                         parent.PeapiClass.nameSpace.CompareTo ("System") == 0) {
274                                         
275                                         if (parent.PeapiClass.name.CompareTo ("ValueType") == 0)
276                                                 is_value_class = true;
277                                         else
278                                         if (parent.PeapiClass.name.CompareTo ("Enum") == 0 )
279                                                 is_enum_class = true;          
280                                 } 
281
282                                 if (outer != null) {
283                                         if (!outer.IsDefined)
284                                                 outer.Define (code_gen);
285                                         classdef = outer.PeapiType.AddNestedClass (attr,
286                                                         name_space, name, parent.PeapiClass);
287                                 } else {
288                                         if (is_value_class || is_enum_class) {
289                                                 // Should probably confirm that the parent is System.ValueType
290                                                 classdef = code_gen.PEFile.AddValueClass (attr,
291                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
292                                         } else {
293                                                 classdef = code_gen.PEFile.AddClass (attr,
294                                                         name_space, name, parent.PeapiClass);
295                                         }
296                                 }
297                         } else {
298                                 if (outer != null) {
299                                         if (!outer.IsDefined)
300                                                 outer.Define (code_gen);
301                                         classdef = outer.PeapiType.AddNestedClass (attr,
302                                                 name_space, name);
303                                 } else {
304                                         if (is_value_class || is_enum_class) {
305                                                 classdef = code_gen.PEFile.AddValueClass (attr,
306                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
307                                         } else {
308                                                 classdef = code_gen.PEFile.AddClass (attr,
309                                                         name_space, name);
310                                         }
311                                 }
312                                 if (FullName == "System.Object")
313                                         classdef.SpecialNoSuper ();
314                         }
315
316                         if (size != -1 || pack != -1)
317                                 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
318
319                         if (impl_list != null) {
320                                 foreach (IClassRef impl in impl_list) {
321                                         impl.Resolve (code_gen);
322                                         classdef.AddImplementedInterface (impl.PeapiClass);
323                                 }
324                         }
325
326                         if (typar_list != null) {
327                                 short index = 0;
328                                 foreach (GenericInfo gi in typar_list) {
329                                         PEAPI.GenericParameter gp = classdef.AddGenericParameter (index++, gi.Id);
330                                         if (gi.ConstraintList != null) {
331                                                 foreach (ITypeRef cnst in gi.ConstraintList) {
332                                                         cnst.Resolve (code_gen);
333                                                         gp.AddConstraint (cnst.PeapiType);
334                                                 }
335                                         }
336                                 }
337                         }
338
339                         is_intransit = false;
340                         is_defined = true;
341
342                         code_gen.AddToDefineContentsList (this);
343                 }
344
345                 public void DefineContents (CodeGen code_gen)
346                 {
347                         ArrayList fielddef_list = new ArrayList ();
348                         foreach (FieldDef fielddef in field_list) {
349                                 fielddef.Define (code_gen, classdef);
350                                 fielddef_list.Add (fielddef.PeapiFieldDef);
351                         }
352
353                         classdef.SetFieldOrder (fielddef_list);
354
355                         foreach (MethodDef methoddef in method_table.Values) {
356                                 methoddef.Define (code_gen, this);
357                         }
358
359                         if (event_list != null) {
360                                 foreach (EventDef eventdef in event_list) {
361                                         eventdef.Define (code_gen, classdef);
362                                 }
363                         }
364
365                         if (property_list != null) {
366                                 foreach (PropertyDef propdef in property_list) {
367                                         propdef.Define (code_gen, classdef);
368                                 }
369
370                         }
371
372                         if (customattr_list != null) {
373                                 foreach (CustomAttr customattr in customattr_list) {
374                                         customattr.AddTo (code_gen, classdef);
375                                         if (customattr.IsSuppressUnmanaged (code_gen))
376                                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
377                                 }
378                         }
379                         
380                         /// Add declarative security to this class
381                         if (decl_sec != null) {
382                                 decl_sec.AddTo (code_gen, classdef);
383                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
384                         }       
385
386                         if (override_list != null) {
387                                 foreach (DictionaryEntry entry in override_list) {
388                                         MethodDef body = (MethodDef) entry.Key;
389                                         DictionaryEntry decl = (DictionaryEntry) entry.Value;
390                                         ITypeRef parent_type = (ITypeRef) decl.Key;
391                                         parent_type.Resolve (code_gen);
392                                         string over_name = (string) decl.Value;
393                                         IMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
394                                                         body.CallConv, over_name, body.ParamTypeList ());
395                                         over_meth.Resolve (code_gen);
396                                         classdef.AddMethodOverride (over_meth.PeapiMethod,
397                                                         body.PeapiMethodDef);
398                                 }
399                         }
400
401                         if (override_long_list != null) {
402                                 foreach (DictionaryEntry entry in override_long_list) {
403                                         string sig = (string) entry.Key;
404                                         IMethodRef decl = (IMethodRef) entry.Value;
405                                         MethodDef body = (MethodDef) method_table[sig];
406                                         decl.Resolve (code_gen);
407                                         classdef.AddMethodOverride (decl.PeapiMethod,
408                                                         body.PeapiMethodDef);
409                                 }
410                         }
411                 }
412
413                 public PEAPI.MethodDef ResolveMethod (string signature, CodeGen code_gen)
414                 {
415                         MethodDef methoddef = (MethodDef) method_table[signature];
416
417                         if (methoddef == null) {
418                                 code_gen.Report.Error ("Unable to resolve method: " + signature);
419                                 Environment.Exit (1);
420                         }
421
422                         return methoddef.Resolve (code_gen, classdef);
423                 }
424
425                 public PEAPI.Method ResolveVarargMethod (string signature,
426                                 CodeGen code_gen, PEAPI.Type[] opt)
427                 {
428                         MethodDef methoddef = (MethodDef) method_table[signature];
429
430                         if (methoddef == null) {
431                                 code_gen.Report.Error ("Unable to resolve method: " + signature);
432                                 Environment.Exit (1);
433                         }
434
435                         methoddef.Resolve (code_gen, classdef);
436                         return methoddef.GetVarargSig (opt);
437                 }
438
439                 public PEAPI.Field ResolveField (string name, CodeGen code_gen)
440                 {
441                         FieldDef fielddef = (FieldDef) field_table[name];
442
443                         return fielddef.Resolve (code_gen, classdef);
444                 }
445
446                 private string MakeFullName ()
447                 {
448                         if (name_space == null || name_space == String.Empty)
449                                 return name;
450
451                         return name_space + "." + name;
452                 }
453         }
454
455 }
456