[corlib] Fix tests for watchOS. (#3131)
[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                 protected PEAPI.Type type;
17                 protected 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         class Triplet : Pair
42         {
43                 string typeMod;
44
45                 public Triplet (PEAPI.Type type, string sig, string typeMod)
46                         : base (type, sig)
47                 {
48                         this.typeMod = typeMod;
49                 }
50
51                 public override int GetHashCode ()
52                 {
53                         return base.GetHashCode () ^ typeMod.GetHashCode ();
54                 }
55
56                 public override bool Equals (object o)
57                 {
58                         Triplet t = o as Triplet;
59                         if (t == null)
60                                 return false;
61
62                         return t.type == type && t.sig == sig && t.typeMod == typeMod;
63                 }
64         }
65
66         public class PeapiTypeRef  {
67
68                 private PEAPI.Type peapi_type;
69                 private bool is_pinned;
70                 private bool is_array;
71                 private bool is_ref;
72                 private bool use_type_spec;
73
74                 private static Hashtable type_table = new Hashtable ();
75
76                 public PeapiTypeRef (PEAPI.Type peapi_type)
77                 {
78                         this.peapi_type = peapi_type;
79                         is_pinned = false;
80                         is_array = false;
81                         is_ref = false;
82                         use_type_spec = false;
83                 }
84
85                 public bool IsPinned {
86                         get { return is_pinned; }
87                 }
88
89                 public bool IsArray {
90                         get { return is_array; }
91                 }
92
93                 public bool IsRef {
94                         get { return is_ref; }
95                 }
96
97                 public bool UseTypeSpec {
98                         get { return use_type_spec; }
99                 }
100
101                 public PEAPI.Type PeapiType {
102                         get { return peapi_type; }
103                 }
104
105                 public void MakeArray ()
106                 {
107                         PEAPI.Type type;
108
109                         use_type_spec = true;
110                         is_array = true;
111
112                         Pair p = new Pair (peapi_type, "[]");
113                         type = type_table [p] as PEAPI.Type;
114                         if (type == null) {
115                                 type = new PEAPI.ZeroBasedArray (peapi_type);
116                                 type_table [p] = type;
117                         }
118                         peapi_type = type;
119                 }
120
121                 public void MakeBoundArray (ArrayList bound_list)
122                 {
123                         use_type_spec = true;
124                         is_array = true;
125
126                         int dimen = bound_list.Count;
127                         int[] lower_array = new int[dimen];
128                         int[] size_array = new int[dimen];
129                         int [] lobounds = null;
130                         int [] sizes = null;
131                         int num_lower, num_sizes;
132                         string sigmod = "";
133                         PEAPI.Type type;
134                         Pair p;
135
136                         sigmod += "[";
137                         for (int i=0; i<bound_list.Count; i++) {
138                                 DictionaryEntry e = (DictionaryEntry) bound_list [i];
139                                 if (e.Key != TypeRef.Ellipsis)
140                                         sigmod += e.Key;
141                                 sigmod += "...";
142                                 if (e.Value != TypeRef.Ellipsis)
143                                         sigmod += e.Value;
144                                 if (i + 1 < bound_list.Count)
145                                         sigmod += ", ";
146                         }
147                         sigmod += "]";
148
149                         p = new Pair (peapi_type, sigmod);
150                         type = type_table [p] as PEAPI.Type;
151                         if (type != null) {
152                                 peapi_type = type;
153                                 return;
154                         }
155
156                         num_sizes = num_lower = 0;
157                         // TODO: There should probably be an error reported if
158                         // something like [3...,3...5] is done
159                         for (int i=0; i<dimen; i++) {
160                                 if (bound_list [i] == null)
161                                         continue;
162                                         
163                                 DictionaryEntry bound = (DictionaryEntry) bound_list [i];
164                                 
165                                 if (bound.Key != TypeRef.Ellipsis) {
166                                         /* Lower bound specified */
167                                         lower_array [i] = (int) bound.Key;
168                                         num_lower = i + 1;
169                                 }
170                                 if (bound.Value != TypeRef.Ellipsis) {
171                                         size_array [i] = (int) bound.Value;
172                                         if (bound.Key != TypeRef.Ellipsis)
173                                                 /* .Value is Upper bound eg [1...5] */
174                                                 size_array [i] -= lower_array [i] - 1;
175                                         num_sizes = i + 1;
176                                 }
177                         }
178
179                         if (num_lower > 0) {
180                                 lobounds = new int [num_lower];
181                                 Array.Copy (lower_array, lobounds, num_lower);
182                         }
183
184                         if (num_sizes > 0) {
185                                 sizes = new int [num_sizes];
186                                 Array.Copy (size_array, sizes, num_sizes);
187                         }
188
189                         peapi_type = new PEAPI.BoundArray (peapi_type,
190                                                 (uint) dimen, lobounds, sizes);
191                         type_table [p] = peapi_type;
192                 }
193
194                 public void MakeManagedPointer ()
195                 {
196                         PEAPI.Type type;
197                         use_type_spec = true;
198                         is_ref = true;
199
200                         Pair p = new Pair (peapi_type, "&");
201                         type = type_table [p] as PEAPI.Type;
202                         if (type == null) {
203                                 type = new PEAPI.ManagedPointer (peapi_type);
204                                 type_table [p] = type;
205                         }
206                         peapi_type = type;
207                 }
208
209                 public void MakeUnmanagedPointer ()
210                 {
211                         PEAPI.Type type;
212                         use_type_spec = true;
213
214                         Pair p = new Pair (peapi_type, "*");
215                         type = type_table [p] as PEAPI.Type;
216                         if (type == null) {
217                                 type = new PEAPI.UnmanagedPointer (peapi_type);
218                                 type_table [p] = type;
219                         }
220                         peapi_type = type;
221                 }
222
223                 public void MakeCustomModified (CodeGen code_gen, PEAPI.CustomModifier modifier,
224                                 BaseTypeRef klass)
225                 {
226                         PEAPI.Type type;
227
228                         use_type_spec = true;
229                         
230                         Pair p = new Triplet (peapi_type, modifier.ToString (), klass.FullName);
231                         type = type_table [p] as PEAPI.Type;
232                         if (type == null) {
233                                 type = GetType (code_gen, modifier, klass);
234                                 type_table [p] = type;
235                         }
236                         peapi_type = type;
237                 }
238
239                 PEAPI.Type GetType (CodeGen code_gen, PEAPI.CustomModifier modifier, BaseTypeRef klass)
240                 {
241                         klass.Resolve (code_gen);
242                         var bcr = klass as BaseClassRef;
243                         if (bcr != null)
244                                 return new PEAPI.CustomModifiedType (peapi_type, modifier, bcr.PeapiClass);
245
246                         var pt = klass as PrimitiveTypeRef;
247                                 return new PEAPI.CustomModifiedType (peapi_type, modifier, code_gen.PEFile.AddPrimitiveType ((PEAPI.PrimitiveType) pt.PeapiType));
248
249                         throw new NotSupportedException (klass.GetType ().ToString ());
250                 }
251
252                 public void MakePinned ()
253                 {
254                         use_type_spec = true;
255                         is_pinned = true;
256                 }
257
258                 public void Resolve (CodeGen code_gen)
259                 {
260
261                 }
262
263
264         }
265
266 }
267