Merge pull request #5444 from hifi/fix-tds-inputoutput
[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, IComparable {
18
19                 private PEAPI.TypeAttr attr;
20                 private string name_space;
21                 private string name;
22                 private bool is_defined;
23                 private bool is_intransit;
24                 private BaseClassRef parent;
25                 private ArrayList impl_list;
26                 private PEAPI.ClassDef classdef;
27                 private Hashtable field_table;
28                 private ArrayList field_list;
29                 private Hashtable method_table;
30                 private ArrayList method_list;
31                 private ArrayList customattr_list;
32                 private DeclSecurity decl_sec;
33                 private ArrayList event_list;
34                 private ArrayList property_list;
35                 private GenericParameters gen_params;
36                 private ArrayList override_list;
37                 private ArrayList override_long_list;
38                 private TypeDef outer;
39
40                 private EventDef current_event;
41                 private PropertyDef current_property;
42
43                 private int size;
44                 private int pack;
45
46                 private bool is_value_class;
47                 private bool is_enum_class;
48
49                 private Location location;
50
51                 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
52                                 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
53                 {
54                         this.attr = attr;
55                         this.parent = parent;
56                         this.impl_list = impl_list;
57                         this.gen_params = gen_params;
58                         this.outer = outer;
59                         this.location = location;
60
61                         field_table = new Hashtable ();
62                         field_list = new ArrayList ();
63
64                         method_table = new Hashtable ();
65                         method_list = new ArrayList ();
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                         ResolveGenParams ();
77
78                         int lastdot = name.LastIndexOf ('.');
79                         /* Namespace . name split should not be done for nested classes */
80                         if (lastdot >= 0 && outer == null) {
81                                 if (name_space == null || name_space == "")
82                                         this.name_space = name.Substring (0, lastdot);
83                                 else
84                                         this.name_space = name_space + "." + name.Substring (0, lastdot);
85                                 this.name = name.Substring (lastdot + 1);
86                         } else {
87                                 this.name_space = name_space;
88                                 this.name = name;
89                         }
90
91                         //Fixup attributes
92                         if (IsInterface)
93                                 this.attr |= PEAPI.TypeAttr.Abstract;
94                 }
95
96                                 public bool NoAutoInherit { get; set; }
97
98                 public string Name {
99                         get { return name; }
100                 }
101
102                 public string FullName {
103                         get { return MakeFullName (); }
104                 }
105
106                 public string NestedFullName {
107                         get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
108                 }
109
110                 public TypeDef OuterType {
111                         get { return outer; }
112                 }
113
114                 public PEAPI.ClassDef PeapiType {
115                         get { return classdef; }
116                 }
117
118                 public PEAPI.ClassDef ClassDef {
119                         get { return classdef; }
120                 }
121
122                 public bool IsGenericType {
123                         get { return (gen_params == null); }
124                 }
125
126                 public bool IsDefined {
127                         get { return is_defined; }
128                 }
129
130                 public EventDef CurrentEvent {
131                         get { return current_event; }
132                 }
133
134                 public PropertyDef CurrentProperty {
135                         get { return current_property; }
136                 }
137
138                 public bool IsInterface {
139                         get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
140                 }
141
142                 public bool IsAbstract {
143                         get { return (attr & PEAPI.TypeAttr.Abstract) != 0; }
144                 }
145
146                 public GenericParameters TypeParameters {
147                         get { return gen_params; }
148                 }
149
150                 public DeclSecurity DeclSecurity {
151                         get {
152                                 if (decl_sec == null)
153                                         decl_sec = new DeclSecurity ();
154                                 return decl_sec;
155                         }
156                 }
157
158                 public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
159                 {
160                         if (override_list == null)
161                                 override_list = new ArrayList ();
162                         override_list.Add (new DictionaryEntry (body,
163                                            new DictionaryEntry (parent, name)));
164                 }
165
166                 public void AddOverride (string sig, BaseMethodRef decl)
167                 {
168                         if (override_long_list == null)
169                                 override_long_list = new ArrayList ();
170                         override_long_list.Add (new DictionaryEntry (sig,
171                                                                 decl));
172                 }
173
174                 public void MakeValueClass ()
175                 {
176                         is_value_class = true;
177                 }
178
179                 public void MakeEnumClass ()
180                 {
181                         is_enum_class = true;
182                 }
183
184                 public void SetSize (int size)
185                 {
186                         this.size = size;
187                 }
188
189                 public void SetPack (int pack)
190                 {
191                         this.pack = pack;
192                 }
193
194                 public void AddFieldDef (FieldDef fielddef)
195                 {
196                         if (IsInterface && !fielddef.IsStatic) {
197                                 Report.Warning ("Non-static field in interface, set to such");
198                                 fielddef.Attributes |= PEAPI.FieldAttr.Static;
199                         }
200
201                         DictionaryEntry entry = new DictionaryEntry (fielddef.Name, fielddef.Type.FullName);
202                         if (field_table [entry] != null)
203                                 Report.Error ("Duplicate field declaration: " + fielddef.Type.FullName + " " + fielddef.Name);
204                         field_table.Add (entry, fielddef);
205                         field_list.Add (fielddef);
206                 }
207
208                 public void AddMethodDef (MethodDef methoddef)
209                 {
210                         if (IsInterface && !methoddef.IsStatic && (!methoddef.IsVirtual || !methoddef.IsAbstract)) {
211                                 Report.Warning (methoddef.StartLocation, "Non-virtual or non-abstract instance method in interface, set to such");
212                                 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
213                         }
214
215                         if (method_table [methoddef.Signature] != null)
216                                 Report.Error (methoddef.StartLocation, "Duplicate method declaration: " + methoddef.Signature);
217
218                         method_table.Add (methoddef.Signature, methoddef);
219                         method_list.Add (methoddef);
220                 }
221
222                 public void BeginEventDef (EventDef event_def)
223                 {
224                         if (current_event != null)
225                                 Report.Error ("An event definition was not closed.");
226
227                         current_event = event_def;
228                 }
229
230                 public void EndEventDef ()
231                 {
232                         if (event_list == null)
233                                 event_list = new ArrayList ();
234
235                         event_list.Add (current_event);
236                         current_event = null;
237                 }
238
239                 public void BeginPropertyDef (PropertyDef property_def)
240                 {
241                         if (current_property != null)
242                                 Report.Error ("A property definition was not closed.");
243
244                         current_property = property_def;
245                 }
246
247                 public void EndPropertyDef ()
248                 {
249                         if (property_list == null)
250                                 property_list = new ArrayList ();
251
252                         property_list.Add (current_property);
253                         current_property = null;
254                 }
255
256                 public void AddCustomAttribute (CustomAttr customattr)
257                 {
258                         if (customattr_list == null)
259                                 customattr_list = new ArrayList ();
260
261                         customattr_list.Add (customattr);
262                 }
263
264                 public GenericParameter GetGenericParam (string id)
265                 {
266                         if (gen_params == null)
267                                 return null;
268                         
269                         return gen_params.GetGenericParam (id);
270                 }
271
272                 public GenericParameter GetGenericParam (int index)
273                 {
274                         if (gen_params == null || index < 0 || index >= gen_params.Count)
275                                 return null;
276                         
277                         return gen_params [index];
278                 }
279
280                 public int GetGenericParamNum (string id)
281                 {
282                         if (gen_params == null)
283                                 return -1;
284                         
285                         return gen_params.GetGenericParamNum (id);
286                 }
287
288                 /* Resolve any GenParams in constraints, parent & impl_list */
289                 private void ResolveGenParams ()
290                 {
291                         if (gen_params == null)
292                                 return;
293
294                         gen_params.ResolveConstraints (gen_params, null);
295
296                         BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
297                         if (gtr != null)
298                                 gtr.Resolve (gen_params, null);
299                         
300                         if (impl_list == null)
301                                 return;
302                                 
303                         foreach (BaseClassRef impl in impl_list) {
304                                 gtr = impl as BaseGenericTypeRef;
305                                 if (gtr != null)
306                                         gtr.Resolve (gen_params, null);
307                         }
308                 }
309
310                 private bool IsValueType (string ns, string name)
311                 {
312                         return (ns == "System" && name == "ValueType");
313                 }
314
315                 private bool IsEnumType (string ns, string name)
316                 {
317                         return (ns == "System" && name == "Enum");
318                 }
319
320                 public void Define (CodeGen code_gen)
321                 {
322                         if (is_defined)
323                                 return;
324
325                         if (is_intransit) {
326                                 // Circular definition
327                                 Report.Error ("Circular definition of class: " + FullName);
328                         }
329
330                         if (outer != null) {
331                                 PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
332
333                                 if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
334                                         /* Nested class, but attr not set accordingly. */
335                                         Report.Warning (location, String.Format ("Nested class '{0}' has non-nested visibility, set to such.", NestedFullName));
336                                         attr = attr ^ vis;
337                                         attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
338                                 }               
339                         }
340                         
341                         if (parent != null) {
342                                 is_intransit = true;
343                                 parent.Resolve (code_gen);
344
345                                 is_intransit = false;
346                                 if (parent.PeapiClass == null) {
347                                         Report.Error ("this type can not be a base type: "
348                                                         + parent);
349                                 }
350
351                                 if (IsValueType (parent.PeapiClass.nameSpace, parent.PeapiClass.name))
352                                         is_value_class = true;
353                                 else if (IsEnumType (parent.PeapiClass.nameSpace, parent.PeapiClass.name)) {
354                                         is_enum_class = true;
355                                         is_value_class = false;
356                                 }
357
358                                 if (!IsValueType (name_space, name) && !IsEnumType (name_space, name) &&
359                                         is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
360
361                                         attr |= PEAPI.TypeAttr.Sealed;
362                                 }
363
364                                 if (outer != null) {
365                                         if (!outer.IsDefined)
366                                                 outer.Define (code_gen);
367                                         classdef = outer.PeapiType.AddNestedClass (attr,
368                                                         name_space, name, parent.PeapiClass);
369                                 } else {
370                                         if (is_value_class || is_enum_class) {
371                                                 // Should probably confirm that the parent is System.ValueType
372                                                 classdef = code_gen.PEFile.AddValueClass (attr,
373                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
374                                         } else {
375                                                 classdef = code_gen.PEFile.AddClass (attr,
376                                                         name_space, name, parent.PeapiClass);
377                                         }
378                                 }
379                         } else {
380                                 if (outer != null) {
381                                         if (!outer.IsDefined)
382                                                 outer.Define (code_gen);
383                                         classdef = outer.PeapiType.AddNestedClass (attr,
384                                                 name_space, name);
385                                 } else {
386                                         if (is_value_class || is_enum_class) {
387                                                 classdef = code_gen.PEFile.AddValueClass (attr,
388                                                         name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
389                                         } else {
390                                                 classdef = code_gen.PEFile.AddClass (attr,
391                                                         name_space, name);
392                                         }
393                                 }
394                                 if (FullName == "System.Object" || NoAutoInherit)
395                                         classdef.SpecialNoSuper ();
396                         }
397
398                         is_defined = true;
399
400                         if (size != -1 || pack != -1)
401                                 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
402
403                         if (impl_list != null) {
404                                 foreach (BaseClassRef impl in impl_list) {
405                                         impl.Resolve (code_gen);
406                                         classdef.AddImplementedInterface (impl.PeapiClass);
407                                 }
408                         }
409
410                         if (gen_params != null)
411                                 gen_params.Resolve (code_gen, classdef);
412
413                         is_intransit = false;
414
415                         code_gen.AddToDefineContentsList (this);
416                 }
417
418                 public void DefineContents (CodeGen code_gen)
419                 {
420                         ArrayList fielddef_list = new ArrayList ();
421                         foreach (FieldDef fielddef in field_list) {
422                                 if (is_enum_class && fielddef.Name == "value__") {
423                                     fielddef.Attributes |= PEAPI.FieldAttr.SpecialName | PEAPI.FieldAttr.RTSpecialName;
424                                 }
425
426                                 fielddef.Define (code_gen, classdef);
427                                 fielddef_list.Add (fielddef.PeapiFieldDef);
428                         }
429
430                         classdef.SetFieldOrder (fielddef_list);
431
432                         foreach (MethodDef methoddef in method_list) {
433                                 methoddef.Define (code_gen);
434                         }
435
436                         if (event_list != null) {
437                                 foreach (EventDef eventdef in event_list) {
438                                         eventdef.Define (code_gen, classdef);
439                                 }
440                         }
441
442                         if (property_list != null) {
443                                 foreach (PropertyDef propdef in property_list) {
444                                         propdef.Define (code_gen, classdef);
445                                 }
446
447                         }
448
449                         if (customattr_list != null) {
450                                 foreach (CustomAttr customattr in customattr_list) {
451                                         customattr.AddTo (code_gen, classdef);
452                                         if (customattr.IsSuppressUnmanaged (code_gen))
453                                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
454                                 }
455                         }
456                         
457                         /// Add declarative security to this class
458                         if (decl_sec != null) {
459                                 decl_sec.AddTo (code_gen, classdef);
460                                 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
461                         }       
462
463                         if (override_list != null) {
464                                 foreach (DictionaryEntry entry in override_list) {
465                                         MethodDef body = (MethodDef) entry.Key;
466                                         DictionaryEntry decl = (DictionaryEntry) entry.Value;
467                                         BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
468                                         parent_type.Resolve (code_gen);
469                                         string over_name = (string) decl.Value;
470                                         BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
471                                                         body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
472                                         over_meth.Resolve (code_gen);
473                                         classdef.AddMethodOverride (over_meth.PeapiMethod,
474                                                         body.PeapiMethodDef);
475                                 }
476                         }
477
478                         if (override_long_list != null) {
479                                 foreach (DictionaryEntry entry in override_long_list) {
480                                         string sig = (string) entry.Key;
481                                         BaseMethodRef decl = (BaseMethodRef) entry.Value;
482                                         MethodDef body = (MethodDef) method_table[sig];
483                                         decl.Resolve (code_gen);
484                                         classdef.AddMethodOverride (decl.PeapiMethod,
485                                                         body.PeapiMethodDef);
486                                 }
487                         }
488                 }
489
490                 public PEAPI.Method ResolveMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
491                         string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
492                 {
493                         string signature = MethodDef.CreateSignature (ret_type, call_conv, name, param, gen_param_count, false);
494                         MethodDef methoddef = (MethodDef) method_table[signature];
495
496                         if (methoddef != null)
497                                 return methoddef.Resolve (code_gen, classdef);
498                         return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
499                 }
500
501                 public PEAPI.Method ResolveVarargMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
502                         string name, BaseTypeRef [] param, int gen_param_count, PEAPI.Type [] opt, CodeGen code_gen)
503                 {
504                         // Only MethodDef sig required to lookup in the method_table
505                         string signature = MethodDef.CreateSignature (ret_type, call_conv, name, param, 0, false);
506                         MethodDef methoddef = (MethodDef) method_table[signature];
507                         if (methoddef != null) {
508                                 methoddef.Resolve (code_gen, classdef);
509                                 return methoddef.GetVarargSig (
510                                                 opt,
511                                                 MethodDef.CreateSignature (ret_type, call_conv, name, param, 0, true));
512                         }
513                         
514                         return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
515                 }
516
517                 private PEAPI.Method ResolveAsMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
518                         string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
519                 {
520                         ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
521                         ExternMethodRef methodref = (ExternMethodRef) type_ref.GetMethodRef (ret_type, call_conv, name, param, gen_param_count);
522                         methodref.Resolve (code_gen);
523
524                         return methodref.PeapiMethod;
525                 }
526
527                 public PEAPI.Field ResolveField (string name, BaseTypeRef ret_type, CodeGen code_gen)
528                 {
529                         FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, ret_type.FullName)];
530                         if (fielddef !=null)
531                                 return fielddef.Resolve (code_gen, classdef);
532
533                         ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
534                         IFieldRef fieldref = type_ref.GetFieldRef (ret_type, name);
535                         fieldref.Resolve (code_gen);
536
537                         return fieldref.PeapiField;
538                 }
539
540                 private string MakeFullName ()
541                 {
542                         if (name_space == null || name_space == String.Empty)
543                                 return name;
544
545                         return name_space + "." + name;
546                 }
547
548                 public int CompareTo (object obj)
549                 {
550                         TypeDef type_def = (TypeDef) obj; 
551
552                         return FullName.CompareTo (type_def.FullName);
553                 }
554         }
555
556 }
557