merge -r 58060:58217
[mono.git] / mcs / ilasm / codegen / PeapiTypeRef.cs
1 //
2 // Mono.ILASM.PeapiTypeRef
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
14 namespace Mono.ILASM {
15         public class Pair {
16                 private PEAPI.Type type;
17                 private string sig;
18
19                 public Pair (PEAPI.Type type, string sig)
20                 {
21                         this.type = type;
22                         this.sig = sig;
23                 }
24
25                 public override int GetHashCode ()
26                 {
27                         return type.GetHashCode () ^ sig.GetHashCode (); 
28                 }
29
30                 public override bool Equals (Object o)
31                 {
32                         Pair p = o as Pair;
33
34                         if (p == null)
35                                 return false;
36                         
37                         return (p.type == this.type && p.sig == this.sig);
38                 }
39         }
40
41         public class PeapiTypeRef  {
42
43                 private PEAPI.Type peapi_type;
44                 private bool is_pinned;
45                 private bool is_array;
46                 private bool is_ref;
47                 private bool use_type_spec;
48
49                 private static Hashtable type_table = new Hashtable ();
50
51                 public PeapiTypeRef (PEAPI.Type peapi_type)
52                 {
53                         this.peapi_type = peapi_type;
54                         is_pinned = false;
55                         is_array = false;
56                         is_ref = false;
57                         use_type_spec = false;
58                 }
59
60                 public bool IsPinned {
61                         get { return is_pinned; }
62                 }
63
64                 public bool IsArray {
65                         get { return is_array; }
66                 }
67
68                 public bool IsRef {
69                         get { return is_ref; }
70                 }
71
72                 public bool UseTypeSpec {
73                         get { return use_type_spec; }
74                 }
75
76                 public PEAPI.Type PeapiType {
77                         get { return peapi_type; }
78                 }
79
80                 public void MakeArray ()
81                 {
82                         PEAPI.Type type;
83
84                         use_type_spec = true;
85                         is_array = true;
86
87                         Pair p = new Pair (peapi_type, "[]");
88                         type = type_table [p] as PEAPI.Type;
89                         if (type == null) {
90                                 type = new PEAPI.ZeroBasedArray (peapi_type);
91                                 type_table [p] = type;
92                         }
93                         peapi_type = type;
94                 }
95
96                 public void MakeBoundArray (ArrayList bound_list)
97                 {
98                         use_type_spec = true;
99                         is_array = true;
100
101                         int dimen = bound_list.Count;
102                         int[] lower_array = new int[dimen];
103                         int[] size_array = new int[dimen];
104                         bool lower_set = false;
105                         bool size_set = false;
106                         bool prev_lower_set = true;
107                         bool prev_size_set = true;
108                         string sigmod = "";
109                         PEAPI.Type type;
110                         Pair p;
111
112                         sigmod += "[";
113                         for (int i=0; i<bound_list.Count; i++) {
114                                 DictionaryEntry e = (DictionaryEntry) bound_list [i];
115                                 if (e.Key != TypeRef.Ellipsis)
116                                         sigmod += e.Key;
117                                 sigmod += "...";
118                                 if (e.Value != TypeRef.Ellipsis)
119                                         sigmod += e.Value;
120                                 if (i + 1 < bound_list.Count)
121                                         sigmod += ", ";
122                         }
123                         sigmod += "]";
124
125                         p = new Pair (peapi_type, sigmod);
126                         type = type_table [p] as PEAPI.Type;
127                         if (type != null) {
128                                 peapi_type = type;
129                                 return;
130                         }
131
132                         // TODO: There should probably be an error reported if
133                         // something like [3...,3...5] is done
134                         for (int i=0; i<dimen; i++) {
135                                 if (bound_list [i] != null) {
136                                         DictionaryEntry bound = (DictionaryEntry) bound_list[i];
137                                         
138                                         if (bound.Key != TypeRef.Ellipsis && prev_lower_set) {
139                                                 lower_array[i] = (int) bound.Key;
140                                                 lower_set = true;
141                                         } else {
142                                                 prev_lower_set = false;
143                                         }
144                                         if (bound.Value != TypeRef.Ellipsis && prev_size_set) {
145                                                 size_array[i] = (int) bound.Value;
146                                                 size_set = true;
147                                         } else {
148                                                 prev_size_set = false;
149                                         }
150                                 }
151                         }
152                         if (lower_set && size_set) {
153                                 peapi_type = new PEAPI.BoundArray (peapi_type,
154                                                 (uint) dimen, lower_array, size_array);
155                         } else if (size_set) {
156                                 peapi_type = new PEAPI.BoundArray (peapi_type,
157                                                 (uint) dimen, size_array);
158                         } else {
159                                 peapi_type = new PEAPI.BoundArray (peapi_type, (uint) dimen);
160                         }
161                         
162                         type_table [p] = peapi_type;
163                 }
164
165                 public void MakeManagedPointer ()
166                 {
167                         PEAPI.Type type;
168                         use_type_spec = true;
169                         is_ref = true;
170
171                         Pair p = new Pair (peapi_type, "&");
172                         type = type_table [p] as PEAPI.Type;
173                         if (type == null) {
174                                 type = new PEAPI.ManagedPointer (peapi_type);
175                                 type_table [p] = type;
176                         }
177                         peapi_type = type;
178                 }
179
180                 public void MakeUnmanagedPointer ()
181                 {
182                         PEAPI.Type type;
183                         use_type_spec = true;
184
185                         Pair p = new Pair (peapi_type, "*");
186                         type = type_table [p] as PEAPI.Type;
187                         if (type == null) {
188                                 type = new PEAPI.UnmanagedPointer (peapi_type);
189                                 type_table [p] = type;
190                         }
191                         peapi_type = type;
192                 }
193
194                 public void MakeCustomModified (CodeGen code_gen, PEAPI.CustomModifier modifier,
195                                 IClassRef klass)
196                 {
197                         PEAPI.Type type;
198
199                         use_type_spec = true;
200                         
201                         Pair p = new Pair (peapi_type, modifier.ToString ());
202                         type = type_table [p] as PEAPI.Type;
203                         if (type == null) {
204                                 klass.Resolve (code_gen);
205                                 type = new PEAPI.CustomModifiedType (peapi_type,
206                                         modifier, klass.PeapiClass);
207                                 type_table [p] = type;
208                         }
209                         peapi_type = type;
210                 }
211
212                 public void MakePinned ()
213                 {
214                         use_type_spec = true;
215                         is_pinned = true;
216                 }
217
218                 public void Resolve (CodeGen code_gen)
219                 {
220
221                 }
222
223
224         }
225
226 }
227