2004-12-27 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / metadata.c
1 /*
2  * metadata.c: Routines for accessing the metadata
3  *
4  * Authors:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001-2002 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <stdio.h> 
13 #include <stdlib.h>
14 #include <string.h>
15 #include <glib.h>
16 #include "metadata.h"
17 #include "tabledefs.h"
18 #include "mono-endian.h"
19 #include "cil-coff.h"
20 #include "tokentype.h"
21 #include "metadata-internals.h"
22 #include "class-internals.h"
23 #include "private.h"
24 #include "class.h"
25
26 static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
27                                          const char *ptr, const char **rptr);
28
29 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
30 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
31 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
32                                                     gboolean signature_only);
33
34 /*
35  * Encoding of the "description" argument:
36  *
37  * identifier [CODE ARG]
38  *
39  * If CODE is ':', then a lookup on table ARG is performed
40  * If CODE is '=', then a lookup in the aliased-table ARG is performed
41  * If CODE is '#', then this encodes a flag, ARG is the flag name. 
42  *
43  * Aliased table for example is `CustomAttributeType' which depending on the
44  * information might refer to different tables.
45  */
46
47 const static MonoMetaTable AssemblySchema [] = {
48         { MONO_MT_UINT32,     "HashId" },
49         { MONO_MT_UINT16,     "Major" },  
50         { MONO_MT_UINT16,     "Minor" },
51         { MONO_MT_UINT16,     "BuildNumber" },
52         { MONO_MT_UINT16,     "RevisionNumber" },
53         { MONO_MT_UINT32,     "Flags" },
54         { MONO_MT_BLOB_IDX,   "PublicKey" },
55         { MONO_MT_STRING_IDX, "Name" },
56         { MONO_MT_STRING_IDX, "Culture" },
57         { MONO_MT_END, NULL }
58 };
59         
60 const static MonoMetaTable AssemblyOSSchema [] = {
61         { MONO_MT_UINT32,     "OSPlatformID" },
62         { MONO_MT_UINT32,     "OSMajor" },
63         { MONO_MT_UINT32,     "OSMinor" },
64         { MONO_MT_END, NULL }
65 };
66
67 const static MonoMetaTable AssemblyProcessorSchema [] = {
68         { MONO_MT_UINT32,     "Processor" },
69         { MONO_MT_END, NULL }
70 };
71
72 const static MonoMetaTable AssemblyRefSchema [] = {
73         { MONO_MT_UINT16,     "Major" },
74         { MONO_MT_UINT16,     "Minor" },
75         { MONO_MT_UINT16,     "Build" },
76         { MONO_MT_UINT16,     "Revision" },
77         { MONO_MT_UINT32,     "Flags" },
78         { MONO_MT_BLOB_IDX,   "PublicKeyOrToken" },
79         { MONO_MT_STRING_IDX, "Name" },
80         { MONO_MT_STRING_IDX, "Culture" },
81         { MONO_MT_BLOB_IDX,   "HashValue" },
82         { MONO_MT_END, NULL }
83 };
84
85 const static MonoMetaTable AssemblyRefOSSchema [] = {
86         { MONO_MT_UINT32,     "OSPlatformID" },
87         { MONO_MT_UINT32,     "OSMajorVersion" },
88         { MONO_MT_UINT32,     "OSMinorVersion" },
89         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
90         { MONO_MT_END, NULL }
91 };
92
93 const static MonoMetaTable AssemblyRefProcessorSchema [] = {
94         { MONO_MT_UINT32,     "Processor" },
95         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
96         { MONO_MT_END, NULL }   
97 };
98
99 const static MonoMetaTable ClassLayoutSchema [] = {
100         { MONO_MT_UINT16,     "PackingSize" },
101         { MONO_MT_UINT32,     "ClassSize" },
102         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
103         { MONO_MT_END, NULL }
104 };
105
106 const static MonoMetaTable ConstantSchema [] = {
107         { MONO_MT_UINT8,      "Type" },
108         { MONO_MT_UINT8,      "PaddingZero" },
109         { MONO_MT_CONST_IDX,  "Parent" },
110         { MONO_MT_BLOB_IDX,   "Value" },
111         { MONO_MT_END, NULL }
112 };
113
114 const static MonoMetaTable CustomAttributeSchema [] = {
115         { MONO_MT_HASCAT_IDX, "Parent" },
116         { MONO_MT_CAT_IDX,    "Type" },
117         { MONO_MT_BLOB_IDX,   "Value" },
118         { MONO_MT_END, NULL }
119 };
120
121 const static MonoMetaTable DeclSecuritySchema [] = {
122         { MONO_MT_UINT16,     "Action" },
123         { MONO_MT_HASDEC_IDX, "Parent" },
124         { MONO_MT_BLOB_IDX,   "PermissionSet" },
125         { MONO_MT_END, NULL }   
126 };
127
128 const static MonoMetaTable EventMapSchema [] = {
129         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
130         { MONO_MT_TABLE_IDX,  "EventList:Event" },
131         { MONO_MT_END, NULL }   
132 };
133
134 const static MonoMetaTable EventSchema [] = {
135         { MONO_MT_UINT16,     "EventFlags#EventAttribute" },
136         { MONO_MT_STRING_IDX, "Name" },
137         { MONO_MT_TABLE_IDX,  "EventType" }, /* TypeDef or TypeRef */
138         { MONO_MT_END, NULL }   
139 };
140
141 const static MonoMetaTable ExportedTypeSchema [] = {
142         { MONO_MT_UINT32,     "Flags" },
143         { MONO_MT_TABLE_IDX,  "TypeDefId" },
144         { MONO_MT_STRING_IDX, "TypeName" },
145         { MONO_MT_STRING_IDX, "TypeNameSpace" },
146         { MONO_MT_IMPL_IDX,   "Implementation" },
147         { MONO_MT_END, NULL }   
148 };
149
150 const static MonoMetaTable FieldSchema [] = {
151         { MONO_MT_UINT16,     "Flags" },
152         { MONO_MT_STRING_IDX, "Name" },
153         { MONO_MT_BLOB_IDX,   "Signature" },
154         { MONO_MT_END, NULL }   
155 };
156 const static MonoMetaTable FieldLayoutSchema [] = {
157         { MONO_MT_UINT32,     "Offset" },
158         { MONO_MT_TABLE_IDX,  "Field:Field" },
159         { MONO_MT_END, NULL }   
160 };
161
162 const static MonoMetaTable FieldMarshalSchema [] = {
163         { MONO_MT_HFM_IDX,    "Parent" },
164         { MONO_MT_BLOB_IDX,   "NativeType" },
165         { MONO_MT_END, NULL }   
166 };
167 const static MonoMetaTable FieldRVASchema [] = {
168         { MONO_MT_UINT32,     "RVA" },
169         { MONO_MT_TABLE_IDX,  "Field:Field" },
170         { MONO_MT_END, NULL }   
171 };
172
173 const static MonoMetaTable FileSchema [] = {
174         { MONO_MT_UINT32,     "Flags" },
175         { MONO_MT_STRING_IDX, "Name" },
176         { MONO_MT_BLOB_IDX,   "Value" }, 
177         { MONO_MT_END, NULL }
178 };
179
180 const static MonoMetaTable ImplMapSchema [] = {
181         { MONO_MT_UINT16,     "MappingFlag" },
182         { MONO_MT_MF_IDX,     "MemberForwarded" },
183         { MONO_MT_STRING_IDX, "ImportName" },
184         { MONO_MT_TABLE_IDX,  "ImportScope:ModuleRef" },
185         { MONO_MT_END, NULL }
186 };
187
188 const static MonoMetaTable InterfaceImplSchema [] = {
189         { MONO_MT_TABLE_IDX,  "Class:TypeDef" }, 
190         { MONO_MT_TDOR_IDX,  "Interface=TypeDefOrRef" },
191         { MONO_MT_END, NULL }
192 };
193
194 const static MonoMetaTable ManifestResourceSchema [] = {
195         { MONO_MT_UINT32,     "Offset" },
196         { MONO_MT_UINT32,     "Flags" },
197         { MONO_MT_STRING_IDX, "Name" },
198         { MONO_MT_IMPL_IDX,   "Implementation" },
199         { MONO_MT_END, NULL }
200 };
201
202 const static MonoMetaTable MemberRefSchema [] = {
203         { MONO_MT_MRP_IDX,    "Class" },
204         { MONO_MT_STRING_IDX, "Name" },
205         { MONO_MT_BLOB_IDX,   "Signature" },
206         { MONO_MT_END, NULL }
207 };
208
209 const static MonoMetaTable MethodSchema [] = {
210         { MONO_MT_UINT32,     "RVA" },
211         { MONO_MT_UINT16,     "ImplFlags#MethodImplAttributes" },
212         { MONO_MT_UINT16,     "Flags#MethodAttribute" },
213         { MONO_MT_STRING_IDX, "Name" },
214         { MONO_MT_BLOB_IDX,   "Signature" },
215         { MONO_MT_TABLE_IDX,  "ParamList:Param" },
216         { MONO_MT_END, NULL }
217 };
218
219 const static MonoMetaTable MethodImplSchema [] = {
220         { MONO_MT_TABLE_IDX,  "Class:TypeDef" },
221         { MONO_MT_MDOR_IDX,   "MethodBody" },
222         { MONO_MT_MDOR_IDX,   "MethodDeclaration" },
223         { MONO_MT_END, NULL }
224 };
225
226 const static MonoMetaTable MethodSemanticsSchema [] = {
227         { MONO_MT_UINT16,     "MethodSemantic" },
228         { MONO_MT_TABLE_IDX,  "Method:Method" },
229         { MONO_MT_HS_IDX,     "Association" },
230         { MONO_MT_END, NULL }
231 };
232
233 const static MonoMetaTable ModuleSchema [] = {
234         { MONO_MT_UINT16,     "Generation" },
235         { MONO_MT_STRING_IDX, "Name" },
236         { MONO_MT_GUID_IDX,   "MVID" },
237         { MONO_MT_GUID_IDX,   "EncID" },
238         { MONO_MT_GUID_IDX,   "EncBaseID" },
239         { MONO_MT_END, NULL }
240 };
241
242 const static MonoMetaTable ModuleRefSchema [] = {
243         { MONO_MT_STRING_IDX, "Name" },
244         { MONO_MT_END, NULL }
245 };
246
247 const static MonoMetaTable NestedClassSchema [] = {
248         { MONO_MT_TABLE_IDX,  "NestedClass:TypeDef" },
249         { MONO_MT_TABLE_IDX,  "EnclosingClass:TypeDef" },
250         { MONO_MT_END, NULL }
251 };
252
253 const static MonoMetaTable ParamSchema [] = {
254         { MONO_MT_UINT16,     "Flags" },
255         { MONO_MT_UINT16,     "Sequence" },
256         { MONO_MT_STRING_IDX, "Name" },
257         { MONO_MT_END, NULL }   
258 };
259
260 const static MonoMetaTable PropertySchema [] = {
261         { MONO_MT_UINT16,     "Flags" },
262         { MONO_MT_STRING_IDX, "Name" },
263         { MONO_MT_BLOB_IDX,   "Type" },
264         { MONO_MT_END, NULL }   
265 };
266
267 const static MonoMetaTable PropertyMapSchema [] = {
268         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
269         { MONO_MT_TABLE_IDX,  "PropertyList:Property" },
270         { MONO_MT_END, NULL }
271 };
272
273 const static MonoMetaTable StandaloneSigSchema [] = {
274         { MONO_MT_BLOB_IDX,   "Signature" },
275         { MONO_MT_END, NULL }
276 };
277
278 const static MonoMetaTable TypeDefSchema [] = {
279         { MONO_MT_UINT32,     "Flags" },
280         { MONO_MT_STRING_IDX, "Name" },
281         { MONO_MT_STRING_IDX, "Namespace" },
282         { MONO_MT_TDOR_IDX,   "Extends" },
283         { MONO_MT_TABLE_IDX,  "FieldList:Field" },
284         { MONO_MT_TABLE_IDX,  "MethodList:Method" },
285         { MONO_MT_END, NULL }
286 };
287
288 const static MonoMetaTable TypeRefSchema [] = {
289         { MONO_MT_RS_IDX,     "ResolutionScope=ResolutionScope" },
290         { MONO_MT_STRING_IDX, "Name" },
291         { MONO_MT_STRING_IDX, "Namespace" },
292         { MONO_MT_END, NULL }
293 };
294
295 const static MonoMetaTable TypeSpecSchema [] = {
296         { MONO_MT_BLOB_IDX,   "Signature" },
297         { MONO_MT_END, NULL }
298 };
299
300 const static MonoMetaTable GenericParamSchema [] = {
301         { MONO_MT_UINT16,     "Number" },
302         { MONO_MT_UINT16,     "Flags" },
303         { MONO_MT_TABLE_IDX,  "Owner" }, /* TypeDef or MethodDef */
304         { MONO_MT_STRING_IDX, "Name" },
305
306         /* soon to be removed */
307         { MONO_MT_TABLE_IDX,  "Kind" }, 
308         
309         { MONO_MT_END, NULL }
310 };
311
312 const static MonoMetaTable MethodSpecSchema [] = {
313         { MONO_MT_MDOR_IDX,   "Method" },
314         { MONO_MT_BLOB_IDX,   "Signature" },
315         { MONO_MT_END, NULL }
316 };
317
318 const static MonoMetaTable GenericParamConstraintSchema [] = {
319         { MONO_MT_TABLE_IDX,  "GenericParam" },
320         { MONO_MT_TDOR_IDX,   "Constraint" },
321         { MONO_MT_END, NULL }
322 };
323
324 const static struct {
325         const MonoMetaTable *table;
326         const char    *name;
327 } tables [] = {
328         /*  0 */ { ModuleSchema,               "Module" },
329         /*  1 */ { TypeRefSchema,              "TypeRef" },
330         /*  2 */ { TypeDefSchema,              "TypeDef" },
331         /*  3 */ { NULL,                       NULL },
332         /*  4 */ { FieldSchema,                "Field" },
333         /*  5 */ { NULL,                       NULL },
334         /*  6 */ { MethodSchema,               "Method" },
335         /*  7 */ { NULL,                       NULL },
336         /*  8 */ { ParamSchema,                "Param" },
337         /*  9 */ { InterfaceImplSchema,        "InterfaceImpl" },
338         /*  A */ { MemberRefSchema,            "MemberRef" },
339         /*  B */ { ConstantSchema,             "Constant" },
340         /*  C */ { CustomAttributeSchema,      "CustomAttribute" },
341         /*  D */ { FieldMarshalSchema,         "FieldMarshal" },
342         /*  E */ { DeclSecuritySchema,         "DeclSecurity" },
343         /*  F */ { ClassLayoutSchema,          "ClassLayout" },
344         /* 10 */ { FieldLayoutSchema,          "FieldLayout" },
345         /* 11 */ { StandaloneSigSchema,        "StandaloneSig" },
346         /* 12 */ { EventMapSchema,             "EventMap" },
347         /* 13 */ { NULL,                       NULL },
348         /* 14 */ { EventSchema,                "Event" },
349         /* 15 */ { PropertyMapSchema,          "PropertyMap" },
350         /* 16 */ { NULL,                       NULL },
351         /* 17 */ { PropertySchema,             "PropertyTable" },
352         /* 18 */ { MethodSemanticsSchema,      "MethodSemantics" },
353         /* 19 */ { MethodImplSchema,           "MethodImpl" },
354         /* 1A */ { ModuleRefSchema,            "ModuleRef" },
355         /* 1B */ { TypeSpecSchema,             "TypeSpec" },
356         /* 1C */ { ImplMapSchema,              "ImplMap" },
357         /* 1D */ { FieldRVASchema,             "FieldRVA" },
358         /* 1E */ { NULL,                       NULL },
359         /* 1F */ { NULL,                       NULL },
360         /* 20 */ { AssemblySchema,             "Assembly" },
361         /* 21 */ { AssemblyProcessorSchema,    "AssemblyProcessor" },
362         /* 22 */ { AssemblyOSSchema,           "AssemblyOS" },
363         /* 23 */ { AssemblyRefSchema,          "AssemblyRef" },
364         /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" },
365         /* 25 */ { AssemblyRefOSSchema,        "AssemblyRefOS" },
366         /* 26 */ { FileSchema,                 "File" },
367         /* 27 */ { ExportedTypeSchema,         "ExportedType" },
368         /* 28 */ { ManifestResourceSchema,     "ManifestResource" },
369         /* 29 */ { NestedClassSchema,          "NestedClass" },
370         /* 2A */ { GenericParamSchema,         "GenericParam" },
371         /* 2B */ { MethodSpecSchema,           "MethodSpec" },
372         /* 2C */ { GenericParamConstraintSchema, "GenericParamConstraint" },
373 };
374
375 /**
376  * mono_meta_table_name:
377  * @table: table index
378  *
379  * Returns: the name for the @table index
380  */
381 const char *
382 mono_meta_table_name (int table)
383 {
384         if ((table < 0) || (table > 0x2c))
385                 return "";
386         
387         return tables [table].name;
388 }
389
390 /* The guy who wrote the spec for this should not be allowed near a
391  * computer again.
392  
393 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
394 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
395 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
396 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
397 inverse of this mapping.
398
399  */
400 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
401 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
402
403 /* Reference: Partition II - 23.2.6 */
404 /*
405  * mono_metadata_compute_size:
406  * @meta: metadata context
407  * @tableindex: metadata table number
408  * @result_bitfield: pointer to guint32 where to store additional info
409  * 
410  * mono_metadata_compute_size() computes the lenght in bytes of a single
411  * row in a metadata table. The size of each column is encoded in the
412  * @result_bitfield return value along with the number of columns in the table.
413  * the resulting bitfield should be handed to the mono_metadata_table_size()
414  * and mono_metadata_table_count() macros.
415  */
416 int
417 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
418 {
419         guint32 bitfield = 0;
420         int size = 0, field_size = 0;
421         int i, n, code;
422         int shift = 0;
423         const MonoMetaTable *table = tables [tableindex].table;
424
425         for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
426                 switch (code){
427                 case MONO_MT_UINT32:
428                         field_size = 4; break;
429                         
430                 case MONO_MT_UINT16:
431                         field_size = 2; break;
432                         
433                 case MONO_MT_UINT8:
434                         field_size = 1; break;
435                         
436                 case MONO_MT_BLOB_IDX:
437                         field_size = meta->idx_blob_wide ? 4 : 2; break;
438                         
439                 case MONO_MT_STRING_IDX:
440                         field_size = meta->idx_string_wide ? 4 : 2; break;
441                         
442                 case MONO_MT_GUID_IDX:
443                         field_size = meta->idx_guid_wide ? 4 : 2; break;
444
445                 case MONO_MT_TABLE_IDX:
446                         /* Uhm, a table index can point to other tables besides the current one
447                          * so, it's not correct to use the rowcount of the current table to
448                          * get the size for this column - lupus 
449                          */
450                         switch (tableindex) {
451                         case MONO_TABLE_ASSEMBLYREFOS:
452                                 g_assert (i == 3);
453                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
454                         case MONO_TABLE_ASSEMBLYPROCESSOR:
455                                 g_assert (i == 1);
456                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
457                         case MONO_TABLE_CLASSLAYOUT:
458                                 g_assert (i == 2);
459                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
460                         case MONO_TABLE_EVENTMAP:
461                                 g_assert (i == 0 || i == 1);
462                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
463                                         idx_size(MONO_TABLE_TYPEDEF); 
464                                 break;
465                         case MONO_TABLE_EVENT:
466                                 g_assert (i == 2);
467                                 field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
468                                 field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
469                                 break;
470                         case MONO_TABLE_EXPORTEDTYPE:
471                                 g_assert (i == 1);
472                                 /* the index is in another metadata file, so it must be 4 */
473                                 field_size = 4; break;
474                         case MONO_TABLE_FIELDLAYOUT:
475                                 g_assert (i == 1);
476                                 field_size = idx_size (MONO_TABLE_FIELD); break;
477                         case MONO_TABLE_FIELDRVA:
478                                 g_assert (i == 1);
479                                 field_size = idx_size (MONO_TABLE_FIELD); break;
480                         case MONO_TABLE_IMPLMAP:
481                                 g_assert (i == 3);
482                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
483                         case MONO_TABLE_INTERFACEIMPL:
484                                 g_assert (i == 0);
485                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
486                         case MONO_TABLE_METHOD:
487                                 g_assert (i == 5);
488                                 field_size = idx_size (MONO_TABLE_PARAM); break;
489                         case MONO_TABLE_METHODIMPL:
490                                 g_assert (i == 0);
491                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
492                         case MONO_TABLE_METHODSEMANTICS:
493                                 g_assert (i == 1);
494                                 field_size = idx_size (MONO_TABLE_METHOD); break;
495                         case MONO_TABLE_NESTEDCLASS:
496                                 g_assert (i == 0 || i == 1);
497                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
498                         case MONO_TABLE_PROPERTYMAP:
499                                 g_assert (i == 0 || i == 1);
500                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
501                                         idx_size(MONO_TABLE_TYPEDEF); 
502                                 break;
503                         case MONO_TABLE_TYPEDEF:
504                                 g_assert (i == 4 || i == 5);
505                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
506                                         idx_size(MONO_TABLE_METHOD);
507                         case MONO_TABLE_GENERICPARAM:
508                                 g_assert (i == 2 || i == 4 || i == 5);
509                                 if (i == 2)
510                                         field_size = MAX (idx_size (MONO_TABLE_METHOD), idx_size (MONO_TABLE_TYPEDEF));
511                                 else if (i == 4)
512                                         field_size = idx_size (MONO_TABLE_TYPEDEF);
513                                 else if (i == 5)
514                                         field_size = idx_size (MONO_TABLE_TYPEDEF);
515                                 break;
516
517                         case MONO_TABLE_GENERICPARAMCONSTRAINT:
518                                 g_assert (i == 0);
519                                 field_size = idx_size (MONO_TABLE_GENERICPARAM);
520                                 break;
521                                 
522                         default:
523                                 g_assert_not_reached ();
524                         }
525                         if (tableindex != MONO_TABLE_EXPORTEDTYPE && field_size != idx_size (tableindex))
526                                 g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
527                         
528                         break;
529
530                         /*
531                          * HasConstant: ParamDef, FieldDef, Property
532                          */
533                 case MONO_MT_CONST_IDX:
534                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
535                                  meta->tables [MONO_TABLE_FIELD].rows);
536                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
537
538                         /* 2 bits to encode tag */
539                         field_size = rtsize (n, 16-2);
540                         break;
541
542                         /*
543                          * HasCustomAttribute: points to any table but
544                          * itself.
545                          */
546                 case MONO_MT_HASCAT_IDX:
547                         /*
548                          * We believe that since the signature and
549                          * permission are indexing the Blob heap,
550                          * we should consider the blob size first
551                          */
552                         /* I'm not a believer - lupus
553                         if (meta->idx_blob_wide){
554                                 field_size = 4;
555                                 break;
556                         }*/
557                         
558                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
559                                  meta->tables [MONO_TABLE_FIELD].rows);
560                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
561                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
562                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
563                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
564                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
565                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
566                         n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
567                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
568                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
569                         n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
570                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
571                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
572                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
573                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
574                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
575                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
576                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
577
578                         /* 5 bits to encode */
579                         field_size = rtsize (n, 16-5);
580                         break;
581
582                         /*
583                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
584                          * MemberRef and String.  
585                          */
586                 case MONO_MT_CAT_IDX:
587                         /* String is a heap, if it is wide, we know the size */
588                         /* See above, nope. 
589                         if (meta->idx_string_wide){
590                                 field_size = 4;
591                                 break;
592                         }*/
593                         
594                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
595                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
596                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
597                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
598
599                         /* 3 bits to encode */
600                         field_size = rtsize (n, 16-3);
601                         break;
602
603                         /*
604                          * HasDeclSecurity: Typedef, MethodDef, Assembly
605                          */
606                 case MONO_MT_HASDEC_IDX:
607                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
608                                  meta->tables [MONO_TABLE_METHOD].rows);
609                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
610
611                         /* 2 bits to encode */
612                         field_size = rtsize (n, 16-2);
613                         break;
614
615                         /*
616                          * Implementation: File, AssemblyRef, ExportedType
617                          */
618                 case MONO_MT_IMPL_IDX:
619                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
620                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
621                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
622
623                         /* 2 bits to encode tag */
624                         field_size = rtsize (n, 16-2);
625                         break;
626
627                         /*
628                          * HasFieldMarshall: FieldDef, ParamDef
629                          */
630                 case MONO_MT_HFM_IDX:
631                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
632                                  meta->tables [MONO_TABLE_PARAM].rows);
633
634                         /* 1 bit used to encode tag */
635                         field_size = rtsize (n, 16-1);
636                         break;
637
638                         /*
639                          * MemberForwarded: FieldDef, MethodDef
640                          */
641                 case MONO_MT_MF_IDX:
642                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
643                                  meta->tables [MONO_TABLE_METHOD].rows);
644
645                         /* 1 bit used to encode tag */
646                         field_size = rtsize (n, 16-1);
647                         break;
648
649                         /*
650                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
651                          * LAMESPEC
652                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
653                          */
654                 case MONO_MT_TDOR_IDX:
655                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
656                                  meta->tables [MONO_TABLE_TYPEREF].rows);
657                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
658
659                         /* 2 bits to encode */
660                         field_size = rtsize (n, 16-2);
661                         break;
662
663                         /*
664                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
665                          */
666                 case MONO_MT_MRP_IDX:
667                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
668                                  meta->tables [MONO_TABLE_TYPEREF].rows);
669                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
670                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
671                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
672                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
673
674                         /* 3 bits to encode */
675                         field_size = rtsize (n, 16 - 3);
676                         break;
677                         
678                 case MONO_MT_MDOR_IDX:
679
680                         /*
681                          * MethodDefOrRef: MethodDef, MemberRef
682                          */
683                 case MONO_MT_HS_IDX:
684                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
685                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
686
687                         /* 1 bit used to encode tag */
688                         field_size = rtsize (n, 16-1);
689                         break;
690
691                         /*
692                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
693                          */
694                 case MONO_MT_RS_IDX:
695                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
696                                  meta->tables [MONO_TABLE_MODULEREF].rows);
697                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
698                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
699
700                         /* 2 bits used to encode tag (ECMA spec claims 3) */
701                         field_size = rtsize (n, 16 - 2);
702                         break;
703                 }
704
705                 /*
706                  * encode field size as follows (we just need to
707                  * distinguish them).
708                  *
709                  * 4 -> 3
710                  * 2 -> 1
711                  * 1 -> 0
712                  */
713                 bitfield |= (field_size-1) << shift;
714                 shift += 2;
715                 size += field_size;
716                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
717         }
718
719         *result_bitfield = (i << 24) | bitfield;
720         return size;
721 }
722
723 /**
724  * mono_metadata_compute_table_bases:
725  * @meta: metadata context to compute table values
726  *
727  * Computes the table bases for the metadata structure.
728  * This is an internal function used by the image loader code.
729  */
730 void
731 mono_metadata_compute_table_bases (MonoImage *meta)
732 {
733         int i;
734         const char *base = meta->tables_base;
735         
736         for (i = 0; i < 64; i++){
737                 if (meta->tables [i].rows == 0)
738                         continue;
739
740                 meta->tables [i].row_size = mono_metadata_compute_size (
741                         meta, i, &meta->tables [i].size_bitfield);
742                 meta->tables [i].base = base;
743                 base += meta->tables [i].rows * meta->tables [i].row_size;
744         }
745 }
746
747 /**
748  * mono_metadata_locate:
749  * @meta: metadata context
750  * @table: table code.
751  * @idx: index of element to retrieve from @table.
752  *
753  * Returns: a pointer to the @idx element in the metadata table
754  * whose code is @table.
755  */
756 const char *
757 mono_metadata_locate (MonoImage *meta, int table, int idx)
758 {
759         /* idx == 0 refers always to NULL */
760         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
761            
762         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
763 }
764
765 /**
766  * mono_metadata_locate_token:
767  * @meta: metadata context
768  * @token: metadata token
769  *
770  * Returns: a pointer to the data in the metadata represented by the
771  * token #token.
772  */
773 const char *
774 mono_metadata_locate_token (MonoImage *meta, guint32 token)
775 {
776         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
777 }
778
779 /**
780  * mono_metadata_get_table:
781  * @table: table to retrieve
782  *
783  * Returns: the MonoMetaTable structure for table @table
784  */
785 const MonoMetaTable *
786 mono_metadata_get_table (MonoMetaTableEnum table)
787 {
788         int x = (int) table;
789
790         g_return_val_if_fail ((x > 0) && (x <= MONO_TABLE_LAST), NULL);
791
792         return tables [table].table;
793 }
794
795 /**
796  * mono_metadata_string_heap:
797  * @meta: metadata context
798  * @index: index into the string heap.
799  *
800  * Returns: an in-memory pointer to the @index in the string heap.
801  */
802 const char *
803 mono_metadata_string_heap (MonoImage *meta, guint32 index)
804 {
805         g_return_val_if_fail (index < meta->heap_strings.size, "");
806         return meta->heap_strings.data + index;
807 }
808
809 /**
810  * mono_metadata_user_string:
811  * @meta: metadata context
812  * @index: index into the user string heap.
813  *
814  * Returns: an in-memory pointer to the @index in the user string heap ("#US").
815  */
816 const char *
817 mono_metadata_user_string (MonoImage *meta, guint32 index)
818 {
819         g_return_val_if_fail (index < meta->heap_us.size, "");
820         return meta->heap_us.data + index;
821 }
822
823 /**
824  * mono_metadata_blob_heap:
825  * @meta: metadata context
826  * @index: index into the blob.
827  *
828  * Returns: an in-memory pointer to the @index in the Blob heap.
829  */
830 const char *
831 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
832 {
833         g_return_val_if_fail (index < meta->heap_blob.size, "");
834         return meta->heap_blob.data + index;
835 }
836
837 /**
838  * mono_metadata_guid_heap:
839  * @meta: metadata context
840  * @index: index into the guid heap.
841  *
842  * Returns: an in-memory pointer to the @index in the guid heap.
843  */
844 const char *
845 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
846 {
847         --index;
848         index *= 16; /* adjust for guid size and 1-based index */
849         g_return_val_if_fail (index < meta->heap_guid.size, "");
850         return meta->heap_guid.data + index;
851 }
852
853 static const char *
854 dword_align (const char *ptr)
855 {
856 #if SIZEOF_VOID_P == 8
857         return (const char *) (((guint64) (ptr + 3)) & ~3);
858 #else
859         return (const char *) (((guint32) (ptr + 3)) & ~3);
860 #endif
861 }
862
863 /**
864  * mono_metadata_decode_row:
865  * @t: table to extract information from.
866  * @idx: index in table.
867  * @res: array of @res_size cols to store the results in
868  *
869  * This decompresses the metadata element @idx in table @t
870  * into the guint32 @res array that has res_size elements
871  */
872 void
873 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
874 {
875         guint32 bitfield = t->size_bitfield;
876         int i, count = mono_metadata_table_count (bitfield);
877         const char *data = t->base + idx * t->row_size;
878         
879         g_assert (res_size == count);
880         
881         for (i = 0; i < count; i++){
882                 int n = mono_metadata_table_size (bitfield, i);
883
884                 switch (n){
885                 case 1:
886                         res [i] = *data; break;
887                 case 2:
888                         res [i] = read16 (data); break;
889                         
890                 case 4:
891                         res [i] = read32 (data); break;
892                         
893                 default:
894                         g_assert_not_reached ();
895                 }
896                 data += n;
897         }
898 }
899
900 /**
901  * mono_metadata_decode_row_col:
902  * @t: table to extract information from.
903  * @idx: index for row in table.
904  * @col: column in the row.
905  *
906  * This function returns the value of column @col from the @idx
907  * row in the table @t.
908  */
909 guint32
910 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
911 {
912         guint32 bitfield = t->size_bitfield;
913         int i;
914         register const char *data = t->base + idx * t->row_size;
915         register int n;
916         
917         g_assert (col < mono_metadata_table_count (bitfield));
918
919         n = mono_metadata_table_size (bitfield, 0);
920         for (i = 0; i < col; ++i) {
921                 data += n;
922                 n = mono_metadata_table_size (bitfield, i + 1);
923         }
924         switch (n){
925         case 1:
926                 return *data;
927         case 2:
928                 return read16 (data);
929         case 4:
930                 return read32 (data);
931         default:
932                 g_assert_not_reached ();
933         }
934         return 0;
935 }
936 /**
937  * mono_metadata_decode_blob_size:
938  * @ptr: pointer to a blob object
939  * @rptr: the new position of the pointer
940  *
941  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
942  *
943  * Returns: the size of the blob object
944  */
945 guint32
946 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
947 {
948         const unsigned char *ptr = (const unsigned char *)xptr;
949         guint32 size;
950         
951         if ((*ptr & 0x80) == 0){
952                 size = ptr [0] & 0x7f;
953                 ptr++;
954         } else if ((*ptr & 0x40) == 0){
955                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
956                 ptr += 2;
957         } else {
958                 size = ((ptr [0] & 0x1f) << 24) +
959                         (ptr [1] << 16) +
960                         (ptr [2] << 8) +
961                         ptr [3];
962                 ptr += 4;
963         }
964         if (rptr)
965                 *rptr = ptr;
966         return size;
967 }
968
969
970 /**
971  * mono_metadata_decode_value:
972  * @ptr: pointer to decode from
973  * @rptr: the new position of the pointer
974  *
975  * This routine decompresses 32-bit values as specified in the "Blob and
976  * Signature" section (22.2)
977  *
978  * Returns: the decoded value
979  */
980 guint32
981 mono_metadata_decode_value (const char *_ptr, const char **rptr)
982 {
983         const unsigned char *ptr = (const unsigned char *) _ptr;
984         unsigned char b = *ptr;
985         guint32 len;
986         
987         if ((b & 0x80) == 0){
988                 len = b;
989                 ++ptr;
990         } else if ((b & 0x40) == 0){
991                 len = ((b & 0x3f) << 8 | ptr [1]);
992                 ptr += 2;
993         } else {
994                 len = ((b & 0x1f) << 24) |
995                         (ptr [1] << 16) |
996                         (ptr [2] << 8) |
997                         ptr [3];
998                 ptr += 4;
999         }
1000         if (rptr)
1001                 *rptr = ptr;
1002         
1003         return len;
1004 }
1005
1006 /*
1007  * mono_metadata_parse_typedef_or_ref:
1008  * @m: a metadata context.
1009  * @ptr: a pointer to an encoded TypedefOrRef in @m
1010  * @rptr: pointer updated to match the end of the decoded stream
1011  *
1012  * Returns: a token valid in the @m metadata decoded from
1013  * the compressed representation.
1014  */
1015 guint32
1016 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1017 {
1018         guint32 token;
1019         token = mono_metadata_decode_value (ptr, &ptr);
1020         if (rptr)
1021                 *rptr = ptr;
1022         return mono_metadata_token_from_dor (token);
1023 }
1024
1025 /*
1026  * mono_metadata_parse_custom_mod:
1027  * @m: a metadata context.
1028  * @dest: storage where the info about the custom modifier is stored (may be NULL)
1029  * @ptr: a pointer to (possibly) the start of a custom modifier list
1030  * @rptr: pointer updated to match the end of the decoded stream
1031  *
1032  * Checks if @ptr points to a type custom modifier compressed representation.
1033  *
1034  * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1035  */
1036 int
1037 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1038 {
1039         MonoCustomMod local;
1040         if ((*ptr == MONO_TYPE_CMOD_OPT) ||
1041             (*ptr == MONO_TYPE_CMOD_REQD)) {
1042                 if (!dest)
1043                         dest = &local;
1044                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1045                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1046                 return TRUE;
1047         }
1048         return FALSE;
1049 }
1050
1051 /*
1052  * mono_metadata_parse_array:
1053  * @m: a metadata context.
1054  * @ptr: a pointer to an encoded array description.
1055  * @rptr: pointer updated to match the end of the decoded stream
1056  *
1057  * Decodes the compressed array description found in the metadata @m at @ptr.
1058  *
1059  * Returns: a #MonoArrayType structure describing the array type
1060  * and dimensions.
1061  */
1062 MonoArrayType *
1063 mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context,
1064                                 const char *ptr, const char **rptr)
1065 {
1066         int i;
1067         MonoArrayType *array = g_new0 (MonoArrayType, 1);
1068         MonoType *etype;
1069         
1070         etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
1071         array->eklass = mono_class_from_mono_type (etype);
1072         array->rank = mono_metadata_decode_value (ptr, &ptr);
1073
1074         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1075         if (array->numsizes)
1076                 array->sizes = g_new0 (int, array->numsizes);
1077         for (i = 0; i < array->numsizes; ++i)
1078                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1079
1080         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1081         if (array->numlobounds)
1082                 array->lobounds = g_new0 (int, array->numlobounds);
1083         for (i = 0; i < array->numlobounds; ++i)
1084                 array->lobounds [i] = mono_metadata_decode_value (ptr, &ptr);
1085
1086         if (rptr)
1087                 *rptr = ptr;
1088         return array;
1089 }
1090
1091 MonoArrayType *
1092 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1093 {
1094         return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
1095 }
1096
1097 /*
1098  * mono_metadata_free_array:
1099  * @array: array description
1100  *
1101  * Frees the array description returned from mono_metadata_parse_array().
1102  */
1103 void
1104 mono_metadata_free_array (MonoArrayType *array)
1105 {
1106         g_free (array->sizes);
1107         g_free (array->lobounds);
1108         g_free (array);
1109 }
1110
1111 /*
1112  * need to add common field and param attributes combinations:
1113  * [out] param
1114  * public static
1115  * public static literal
1116  * private
1117  * private static
1118  * private static literal
1119  */
1120 static const MonoType
1121 builtin_types[] = {
1122         /* data, attrs, type,              nmods, byref, pinned */
1123         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
1124         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
1125         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
1126         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
1127         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
1128         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
1129         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
1130         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
1131         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
1132         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
1133         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1134         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1135         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1136         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1137         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1138         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1139         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1140         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1141         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1142         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1143         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1144         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1145         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1146         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1147         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1148         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1149         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1150         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1151         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0},
1152         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1153         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1154         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1155         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1156         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1157 };
1158
1159 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1160
1161 static GHashTable *type_cache = NULL;
1162 static GHashTable *generic_inst_cache = NULL;
1163 static GHashTable *generic_class_cache = NULL;
1164 static int next_generic_inst_id = 0;
1165
1166 /*
1167  * MonoTypes with modifies are never cached, so we never check or use that field.
1168  */
1169 static guint
1170 mono_type_hash (gconstpointer data)
1171 {
1172         const MonoType *type = (const MonoType *) data;
1173         return type->type | (type->byref << 8) | (type->attrs << 9);
1174 }
1175
1176 static gint
1177 mono_type_equal (gconstpointer ka, gconstpointer kb)
1178 {
1179         const MonoType *a = (const MonoType *) ka;
1180         const MonoType *b = (const MonoType *) kb;
1181         
1182         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1183                 return 0;
1184         /* need other checks */
1185         return 1;
1186 }
1187
1188 static guint
1189 mono_generic_inst_hash (gconstpointer data)
1190 {
1191         const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1192         return ginst->type_argc | (ginst->is_open << 8);
1193 }
1194
1195 static gboolean
1196 mono_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1197 {
1198         const MonoGenericInst *a = (const MonoGenericInst *) ka;
1199         const MonoGenericInst *b = (const MonoGenericInst *) kb;
1200         int i;
1201
1202         if ((a->is_open != b->is_open) || (a->type_argc != b->type_argc))
1203                 return FALSE;
1204         for (i = 0; i < a->type_argc; ++i) {
1205                 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], FALSE))
1206                         return FALSE;
1207         }
1208         return TRUE;
1209 }
1210
1211 static guint
1212 mono_generic_class_hash (gconstpointer data)
1213 {
1214         const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1215         return mono_metadata_type_hash (&gclass->container_class->byval_arg);
1216 }
1217
1218 static gboolean
1219 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1220 {
1221         const MonoGenericClass *a = (const MonoGenericClass *) ka;
1222         const MonoGenericClass *b = (const MonoGenericClass *) kb;
1223
1224         return _mono_metadata_generic_class_equal (a, b, FALSE);
1225 }
1226
1227 /**
1228  * mono_metadata_init:
1229  *
1230  *  Initialize the global variables of this module.
1231  */
1232 void
1233 mono_metadata_init (void)
1234 {
1235         int i;
1236
1237         type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1238         generic_inst_cache = g_hash_table_new (mono_generic_inst_hash, mono_generic_inst_equal);
1239         generic_class_cache = g_hash_table_new (mono_generic_class_hash, mono_generic_class_equal);
1240
1241         for (i = 0; i < NBUILTIN_TYPES (); ++i)
1242                 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1243 }
1244
1245 /**
1246  * mono_metadata_parse_type:
1247  * @m: metadata context
1248  * @mode: king of type that may be found at @ptr
1249  * @opt_attrs: optional attributes to store in the returned type
1250  * @ptr: pointer to the type representation
1251  * @rptr: pointer updated to match the end of the decoded stream
1252  * 
1253  * Decode a compressed type description found at @ptr in @m.
1254  * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1255  * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1256  * This function can be used to decode type descriptions in method signatures,
1257  * field signatures, locals signatures etc.
1258  *
1259  * To parse a generic type, `generic_container' points to the current class'es
1260  * (the `generic_container' field in the MonoClass) or the current generic method's
1261  * (the `generic_container' field in the MonoMethodNormal) generic container.
1262  * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1263  * this MonoGenericContainer.
1264  *
1265  * Returns: a #MonoType structure representing the decoded type.
1266  */
1267 MonoType*
1268 mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode,
1269                                short opt_attrs, const char *ptr, const char **rptr)
1270 {
1271         MonoType *type, *cached;
1272         MonoType stype;
1273         gboolean byref = FALSE;
1274         gboolean pinned = FALSE;
1275         const char *tmp_ptr;
1276         int count = 0;
1277         gboolean found;
1278
1279         /*
1280          * According to the spec, custom modifiers should come before the byref
1281          * flag, but the IL produced by ilasm from the following signature:
1282          *   object modopt(...) &
1283          * starts with a byref flag, followed by the modifiers. (bug #49802)
1284          * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1285          * it would be better to treat byref as real type constructor instead of
1286          * a modifier...
1287          * Also, pinned should come before anything else, but some MSV++ produced
1288          * assemblies violate this (#bug 61990).
1289          */
1290
1291         /* Count the modifiers first */
1292         tmp_ptr = ptr;
1293         found = TRUE;
1294         while (found) {
1295                 switch (*tmp_ptr) {
1296                 case MONO_TYPE_PINNED:
1297                 case MONO_TYPE_BYREF:
1298                         ++tmp_ptr;
1299                         break;
1300                 case MONO_TYPE_CMOD_REQD:
1301                 case MONO_TYPE_CMOD_OPT:
1302                         count ++;
1303                         mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1304                         break;
1305                 default:
1306                         found = FALSE;
1307                 }
1308         }
1309
1310         if (count) {
1311                 type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
1312                 type->num_mods = count;
1313                 if (count > 64)
1314                         g_warning ("got more than 64 modifiers in type");
1315         }
1316         else {
1317                 type = &stype;
1318                 memset (type, 0, sizeof (MonoType));
1319         }
1320
1321         /* Parse pinned, byref and custom modifiers */
1322         found = TRUE;
1323         count = 0;
1324         while (found) {
1325                 switch (*ptr) {
1326                 case MONO_TYPE_PINNED:
1327                         pinned = TRUE;
1328                         ++ptr;
1329                         break;
1330                 case MONO_TYPE_BYREF:
1331                         byref = TRUE;
1332                         ++ptr;
1333                         break;
1334                 case MONO_TYPE_CMOD_REQD:
1335                 case MONO_TYPE_CMOD_OPT:
1336                         mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1337                         count ++;
1338                         break;
1339                 default:
1340                         found = FALSE;
1341                 }
1342         }
1343         
1344         type->attrs = opt_attrs;
1345         type->byref = byref;
1346         type->pinned = pinned ? 1 : 0;
1347
1348         do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr);
1349
1350         if (rptr)
1351                 *rptr = ptr;
1352
1353         
1354         /* FIXME: remove the != MONO_PARSE_PARAM condition, this accounts for
1355          * almost 10k (about 2/3rds) of all MonoType's we create.
1356          */
1357         if (mode != MONO_PARSE_PARAM && !type->num_mods) {
1358                 /* no need to free type here, because it is on the stack */
1359                 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1360                         if (type->byref)
1361                                 return &type->data.klass->this_arg;
1362                         else
1363                                 return &type->data.klass->byval_arg;
1364                 }
1365                 /* No need to use locking since nobody is modifying the hash table */
1366                 if ((cached = g_hash_table_lookup (type_cache, type)))
1367                         return cached;
1368         }
1369         
1370         /*printf ("%x%c %s\n", type->attrs, type->pinned ? 'p' : ' ', mono_type_full_name (type));*/
1371         
1372         if (type == &stype)
1373                 type = g_memdup (&stype, sizeof (MonoType));
1374         return type;
1375 }
1376
1377 MonoType*
1378 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1379                           const char *ptr, const char **rptr)
1380 {
1381         return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
1382 }
1383
1384 /*
1385  * mono_metadata_parse_signature:
1386  * @image: metadata context
1387  * @toke: metadata token
1388  *
1389  * Decode a method signature stored in the STANDALONESIG table
1390  *
1391  * Returns: a MonoMethodSignature describing the signature.
1392  */
1393 MonoMethodSignature *
1394 mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContext *generic_context, guint32 token)
1395 {
1396         MonoTableInfo *tables = image->tables;
1397         guint32 idx = mono_metadata_token_index (token);
1398         guint32 sig;
1399         const char *ptr;
1400
1401         if (image->dynamic)
1402                 return mono_lookup_dynamic_token (image, token);
1403
1404         g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1405                 
1406         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1407
1408         ptr = mono_metadata_blob_heap (image, sig);
1409         mono_metadata_decode_blob_size (ptr, &ptr);
1410
1411         return mono_metadata_parse_method_signature_full (image, generic_context, FALSE, ptr, NULL); 
1412 }
1413
1414 MonoMethodSignature *
1415 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1416 {
1417         return mono_metadata_parse_signature_full (image, NULL, token);
1418 }
1419
1420 MonoMethodSignature*
1421 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1422 {
1423         MonoMethodSignature *sig;
1424
1425         /* later we want to allocate signatures with mempools */
1426         sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1427         sig->param_count = nparams;
1428         sig->sentinelpos = -1;
1429
1430         return sig;
1431 }
1432
1433 MonoMethodSignature*
1434 mono_metadata_signature_dup (MonoMethodSignature *sig)
1435 {
1436         int sigsize;
1437
1438         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1439         return g_memdup (sig, sigsize);
1440 }
1441
1442 /*
1443  * mono_metadata_parse_method_signature:
1444  * @m: metadata context
1445  * @def: the MethodDef index or 0 for Ref signatures.
1446  * @ptr: pointer to the signature metadata representation
1447  * @rptr: pointer updated to match the end of the decoded stream
1448  *
1449  * Decode a method signature stored at @ptr.
1450  *
1451  * Returns: a MonoMethodSignature describing the signature.
1452  */
1453 MonoMethodSignature *
1454 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContext *generic_context,
1455                                            int def, const char *ptr, const char **rptr)
1456 {
1457         MonoMethodSignature *method;
1458         int i, ret_attrs = 0, *pattrs = NULL;
1459         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1460         guint32 gen_param_count = 0;
1461         gboolean is_open = FALSE;
1462         MonoGenericContext *context = NULL;
1463
1464         if (*ptr & 0x10)
1465                 gen_param_count = 1;
1466         if (*ptr & 0x20)
1467                 hasthis = 1;
1468         if (*ptr & 0x40)
1469                 explicit_this = 1;
1470         call_convention = *ptr & 0x0F;
1471         ptr++;
1472         if (gen_param_count)
1473                 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
1474         param_count = mono_metadata_decode_value (ptr, &ptr);
1475         pattrs = g_new0 (int, param_count);
1476
1477         if (def) {
1478                 MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1479                 MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1480                 guint32 cols [MONO_PARAM_SIZE];
1481                 guint lastp, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1482
1483                 if (def < methodt->rows)
1484                         lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1485                 else
1486                         lastp = paramt->rows + 1;
1487                 for (i = param_index; i < lastp; ++i) {
1488                         mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1489                         if (!cols [MONO_PARAM_SEQUENCE])
1490                                 ret_attrs = cols [MONO_PARAM_FLAGS];
1491                         else
1492                                 pattrs [cols [MONO_PARAM_SEQUENCE] - 1] = cols [MONO_PARAM_FLAGS];
1493                 }
1494         }
1495         method = mono_metadata_signature_alloc (m, param_count);
1496         method->hasthis = hasthis;
1497         method->explicit_this = explicit_this;
1498         method->call_convention = call_convention;
1499         method->generic_param_count = gen_param_count;
1500
1501         if (gen_param_count)
1502                 method->has_type_parameters = 1;
1503
1504         if (gen_param_count && (!generic_context || !generic_context->container->is_method)) {
1505                 MonoGenericContainer *container = g_new0 (MonoGenericContainer, 1);
1506
1507                 if (generic_context)
1508                         container->parent = generic_context->container;
1509                 container->is_signature = 1;
1510
1511                 context = &container->context;
1512                 container->context.container = container;
1513
1514                 container->type_argc = gen_param_count;
1515                 container->type_params = g_new0 (MonoGenericParam, gen_param_count);
1516
1517                 for (i = 0; i < gen_param_count; i++) {
1518                         container->type_params [i].owner = container;
1519                         container->type_params [i].num = i;
1520                 }
1521         } else
1522                 context = generic_context;
1523
1524         if (call_convention != 0xa) {
1525                 method->ret = mono_metadata_parse_type_full (m, context, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
1526                 is_open = mono_class_is_open_constructed_type (method->ret);
1527         }
1528
1529         if (method->param_count) {
1530                 method->sentinelpos = -1;
1531                 
1532                 for (i = 0; i < method->param_count; ++i) {
1533                         if (*ptr == MONO_TYPE_SENTINEL) {
1534                                 if (method->call_convention != MONO_CALL_VARARG || def)
1535                                                 g_error ("found sentinel for methoddef or no vararg method");
1536                                 method->sentinelpos = i;
1537                                 ptr++;
1538                         }
1539                         method->params [i] = mono_metadata_parse_type_full (
1540                                 m, context, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
1541                         if (!is_open)
1542                                 is_open = mono_class_is_open_constructed_type (method->params [i]);
1543                 }
1544         }
1545
1546         method->has_type_parameters = is_open;
1547
1548         if (def && (method->call_convention == MONO_CALL_VARARG))
1549                 method->sentinelpos = method->param_count;
1550
1551         g_free (pattrs);
1552
1553         if (rptr)
1554                 *rptr = ptr;
1555         /*
1556          * Add signature to a cache and increase ref count...
1557          */
1558         return method;
1559 }
1560
1561 MonoMethodSignature *
1562 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
1563 {
1564         return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
1565 }
1566
1567 /*
1568  * mono_metadata_free_method_signature:
1569  * @sig: signature to destroy
1570  *
1571  * Free the memory allocated in the signature @sig.
1572  */
1573 void
1574 mono_metadata_free_method_signature (MonoMethodSignature *sig)
1575 {
1576         int i;
1577         mono_metadata_free_type (sig->ret);
1578         for (i = 0; i < sig->param_count; ++i)
1579                 mono_metadata_free_type (sig->params [i]);
1580
1581         g_free (sig);
1582 }
1583
1584 MonoGenericInst *
1585 mono_metadata_lookup_generic_inst (MonoGenericInst *ginst)
1586 {
1587         MonoGenericInst *cached;
1588         int i;
1589
1590         cached = g_hash_table_lookup (generic_inst_cache, ginst);
1591         if (cached) {
1592                 for (i = 0; i < ginst->type_argc; i++)
1593                         mono_metadata_free_type (ginst->type_argv [i]);
1594                 g_free (ginst->type_argv);
1595                 g_free (ginst);
1596                 return cached;
1597         }
1598
1599         ginst->id = ++next_generic_inst_id;
1600         g_hash_table_insert (generic_inst_cache, ginst, ginst);
1601
1602         return ginst;
1603 }
1604
1605 MonoGenericClass *
1606 mono_metadata_lookup_generic_class (MonoGenericClass *gclass)
1607 {
1608         MonoGenericClass *cached;
1609         int i;
1610
1611         cached = g_hash_table_lookup (generic_class_cache, gclass);
1612         if (cached)
1613                 return cached;
1614
1615         g_hash_table_insert (generic_class_cache, gclass, gclass);
1616         return NULL;
1617 }
1618
1619 MonoGenericInst *
1620 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
1621 {
1622         MonoGenericInst *nginst, *cached;
1623         int i;
1624
1625         nginst = g_new0 (MonoGenericInst, 1);
1626         nginst->type_argc = ginst->type_argc;
1627         nginst->type_argv = g_new0 (MonoType*, nginst->type_argc);
1628
1629         for (i = 0; i < nginst->type_argc; i++) {
1630                 MonoType *t = ginst->type_argv [i];
1631
1632                 nginst->type_argv [i] = mono_class_inflate_generic_type (t, context);
1633
1634                 if (!nginst->is_open)
1635                         nginst->is_open = mono_class_is_open_constructed_type (nginst->type_argv [i]);
1636         }
1637
1638         return mono_metadata_lookup_generic_inst (nginst);
1639 }
1640
1641 MonoGenericInst *
1642 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context,
1643                                   int count, const char *ptr, const char **rptr)
1644 {
1645         MonoGenericInst *ginst;
1646         int i;
1647
1648         ginst = g_new0 (MonoGenericInst, 1);
1649         ginst->type_argc = count;
1650         ginst->type_argv = g_new0 (MonoType*, count);
1651
1652         for (i = 0; i < ginst->type_argc; i++) {
1653                 MonoType *t = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
1654
1655                 ginst->type_argv [i] = t;
1656                 if (!ginst->is_open)
1657                         ginst->is_open = mono_class_is_open_constructed_type (t);
1658         }
1659
1660         if (rptr)
1661                 *rptr = ptr;
1662
1663         return mono_metadata_lookup_generic_inst (ginst);
1664 }
1665
1666 static void
1667 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
1668                                       const char *ptr, const char **rptr)
1669 {
1670         MonoGenericClass *gclass = g_new0 (MonoGenericClass, 1);
1671         MonoGenericContainer *container;
1672         MonoGenericClass *cached;
1673         MonoGenericInst *ginst;
1674         MonoClass *gklass;
1675         MonoType *gtype;
1676         int i, count;
1677
1678         type->data.generic_class = gclass;
1679
1680         gclass->context = g_new0 (MonoGenericContext, 1);
1681         gclass->context->gclass = gclass;
1682
1683         gclass->klass = g_new0 (MonoClass, 1);
1684
1685         gtype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
1686         gclass->container_class = gklass = mono_class_from_mono_type (gtype);
1687
1688         g_assert ((gclass->context->container = gklass->generic_container) != NULL);
1689         count = mono_metadata_decode_value (ptr, &ptr);
1690
1691         /*
1692          * Create the klass before parsing the type arguments.
1693          * This is required to support "recursive" definitions.
1694          * See mcs/tests/gen-23.cs for an example.
1695          */
1696
1697         gclass->init_pending = TRUE;
1698
1699         mono_class_create_generic (gclass);
1700
1701         gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr);
1702
1703         mono_class_create_generic_2 (gclass);
1704
1705         if (rptr)
1706                 *rptr = ptr;
1707
1708         /*
1709          * We may be called multiple times on different metadata to create the same
1710          * instantiated type.  This happens for instance if we're part of a method or
1711          * local variable signature.
1712          *
1713          * It's important to return the same MonoGenericClass * for each particualar
1714          * instantiation of a generic type (ie "Stack<Int32>") to make static fields
1715          * work.
1716          *
1717          * According to the spec ($26.1.5), a static variable in a generic class
1718          * declaration is shared amongst all instances of the same closed constructed
1719          * type.
1720          */
1721
1722         cached = g_hash_table_lookup (generic_class_cache, gclass);
1723         if (cached) {
1724                 g_free (gclass->klass);
1725                 g_free (gclass);
1726
1727                 type->data.generic_class = cached;
1728                 return;
1729         } else {
1730                 g_hash_table_insert (generic_class_cache, gclass, gclass);
1731
1732                 mono_stats.generic_instance_count++;
1733                 mono_stats.generics_metadata_size += sizeof (MonoGenericClass) +
1734                         sizeof (MonoGenericContext) +
1735                         gclass->inst->type_argc * sizeof (MonoType);
1736         }
1737
1738         gclass->init_pending = FALSE;
1739 }
1740
1741 /* 
1742  * do_mono_metadata_parse_generic_param:
1743  * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
1744  *                     see mono_metadata_parse_type_full() for details.
1745  * Internal routine to parse a generic type parameter.
1746  */
1747 static MonoGenericParam *
1748 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context,
1749                                    gboolean is_mvar, const char *ptr, const char **rptr)
1750 {
1751         MonoGenericContainer *generic_container;
1752         int index;
1753
1754         index = mono_metadata_decode_value (ptr, &ptr);
1755         if (rptr)
1756                 *rptr = ptr;
1757
1758         g_assert (generic_context);
1759         if (generic_context->gmethod)
1760                 generic_container = generic_context->gmethod->container;
1761         else if (generic_context->gclass)
1762                 generic_container = generic_context->gclass->container_class->generic_container;
1763         else
1764                 generic_container = generic_context->container;
1765
1766         if (!is_mvar) {
1767                 g_assert (generic_container);
1768                 if (generic_container->parent) {
1769                         /*
1770                          * The current MonoGenericContainer is a generic method -> its `parent'
1771                          * points to the containing class'es container.
1772                          */
1773                         generic_container = generic_container->parent;
1774                 }
1775                 g_assert (generic_container && !generic_container->is_method);
1776                 g_assert (index < generic_container->type_argc);
1777
1778                 return &generic_container->type_params [index];
1779         } else {
1780                 g_assert (generic_container && (generic_container->is_method || generic_container->is_signature));
1781                 g_assert (index < generic_container->type_argc);
1782
1783                 return &generic_container->type_params [index];
1784         }
1785 }
1786
1787 /* 
1788  * do_mono_metadata_parse_type:
1789  * @type: MonoType to be filled in with the return value
1790  * @
1791  * Internal routine used to "fill" the contents of @type from an 
1792  * allocated pointer.  This is done this way to avoid doing too
1793  * many mini-allocations (particularly for the MonoFieldType which
1794  * most of the time is just a MonoType, but sometimes might be augmented).
1795  *
1796  * This routine is used by mono_metadata_parse_type and
1797  * mono_metadata_parse_field_type
1798  *
1799  * This extracts a Type as specified in Partition II (22.2.12) 
1800  */
1801 static void
1802 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
1803                              const char *ptr, const char **rptr)
1804 {
1805         type->type = mono_metadata_decode_value (ptr, &ptr);
1806         
1807         switch (type->type){
1808         case MONO_TYPE_VOID:
1809         case MONO_TYPE_BOOLEAN:
1810         case MONO_TYPE_CHAR:
1811         case MONO_TYPE_I1:
1812         case MONO_TYPE_U1:
1813         case MONO_TYPE_I2:
1814         case MONO_TYPE_U2:
1815         case MONO_TYPE_I4:
1816         case MONO_TYPE_U4:
1817         case MONO_TYPE_I8:
1818         case MONO_TYPE_U8:
1819         case MONO_TYPE_R4:
1820         case MONO_TYPE_R8:
1821         case MONO_TYPE_I:
1822         case MONO_TYPE_U:
1823         case MONO_TYPE_STRING:
1824         case MONO_TYPE_OBJECT:
1825         case MONO_TYPE_TYPEDBYREF:
1826                 break;
1827         case MONO_TYPE_VALUETYPE:
1828         case MONO_TYPE_CLASS: {
1829                 guint32 token;
1830                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1831                 type->data.klass = mono_class_get (m, token);
1832                 break;
1833         }
1834         case MONO_TYPE_SZARRAY: {
1835                 MonoType *etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
1836                 type->data.klass = mono_class_from_mono_type (etype);
1837                 mono_metadata_free_type (etype);
1838                 break;
1839         }
1840         case MONO_TYPE_PTR:
1841                 type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
1842                 break;
1843         case MONO_TYPE_FNPTR:
1844                 type->data.method = mono_metadata_parse_method_signature_full (m, generic_context, 0, ptr, &ptr);
1845                 break;
1846         case MONO_TYPE_ARRAY:
1847                 type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr);
1848                 break;
1849
1850         case MONO_TYPE_MVAR:
1851                 type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr);
1852                 break;
1853
1854         case MONO_TYPE_VAR:
1855                 type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr);
1856                 break;
1857
1858         case MONO_TYPE_GENERICINST:
1859                 do_mono_metadata_parse_generic_class (type, m, generic_context, ptr, &ptr);
1860                 break;
1861                 
1862         default:
1863                 g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
1864         }
1865         
1866         if (rptr)
1867                 *rptr = ptr;
1868 }
1869
1870 /*
1871  * mono_metadata_free_type:
1872  * @type: type to free
1873  *
1874  * Free the memory allocated for type @type.
1875  */
1876 void
1877 mono_metadata_free_type (MonoType *type)
1878 {
1879         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
1880                 return;
1881         
1882         switch (type->type){
1883         case MONO_TYPE_OBJECT:
1884         case MONO_TYPE_STRING:
1885                 if (!type->data.klass)
1886                         break;
1887                 /* fall through */
1888         case MONO_TYPE_CLASS:
1889         case MONO_TYPE_VALUETYPE:
1890                 if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
1891                         return;
1892                 break;
1893         case MONO_TYPE_PTR:
1894                 mono_metadata_free_type (type->data.type);
1895                 break;
1896         case MONO_TYPE_FNPTR:
1897                 mono_metadata_free_method_signature (type->data.method);
1898                 break;
1899         case MONO_TYPE_ARRAY:
1900                 mono_metadata_free_array (type->data.array);
1901                 break;
1902         }
1903         g_free (type);
1904 }
1905
1906 #if 0
1907 static void
1908 hex_dump (const char *buffer, int base, int count)
1909 {
1910         int show_header = 1;
1911         int i;
1912
1913         if (count < 0){
1914                 count = -count;
1915                 show_header = 0;
1916         }
1917         
1918         for (i = 0; i < count; i++){
1919                 if (show_header)
1920                         if ((i % 16) == 0)
1921                                 printf ("\n0x%08x: ", (unsigned char) base + i);
1922
1923                 printf ("%02x ", (unsigned char) (buffer [i]));
1924         }
1925         fflush (stdout);
1926 }
1927 #endif
1928
1929 /** 
1930  * @mh: The Method header
1931  * @ptr: Points to the beginning of the Section Data (25.3)
1932  */
1933 static void
1934 parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr)
1935 {
1936         unsigned char sect_data_flags;
1937         const unsigned char *sptr;
1938         int is_fat;
1939         guint32 sect_data_len;
1940         
1941         while (1) {
1942                 /* align on 32-bit boundary */
1943                 /* FIXME: not 64-bit clean code */
1944                 sptr = ptr = dword_align (ptr); 
1945                 sect_data_flags = *ptr;
1946                 ptr++;
1947                 
1948                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1949                 if (is_fat) {
1950                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
1951                         ptr += 3;
1952                 } else {
1953                         sect_data_len = ptr [0];
1954                         ++ptr;
1955                 }
1956                 /*
1957                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
1958                 hex_dump (sptr, 0, sect_data_len+8);
1959                 g_print ("\nheader: ");
1960                 hex_dump (sptr-4, 0, 4);
1961                 g_print ("\n");
1962                 */
1963                 
1964                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1965                         const unsigned char *p = dword_align (ptr);
1966                         int i;
1967                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
1968                         /* we could just store a pointer if we don't need to byteswap */
1969                         mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
1970                         for (i = 0; i < mh->num_clauses; ++i) {
1971                                 MonoExceptionClause *ec = &mh->clauses [i];
1972                                 guint32 tof_value;
1973                                 if (is_fat) {
1974                                         ec->flags = read32 (p);
1975                                         p += 4;
1976                                         ec->try_offset = read32 (p);
1977                                         p += 4;
1978                                         ec->try_len = read32 (p);
1979                                         p += 4;
1980                                         ec->handler_offset = read32 (p);
1981                                         p += 4;
1982                                         ec->handler_len = read32 (p);
1983                                         p += 4;
1984                                         tof_value = read32 (p);
1985                                         p += 4;
1986                                 } else {
1987                                         ec->flags = read16 (p);
1988                                         p += 2;
1989                                         ec->try_offset = read16 (p);
1990                                         p += 2;
1991                                         ec->try_len = *p;
1992                                         ++p;
1993                                         ec->handler_offset = read16 (p);
1994                                         p += 2;
1995                                         ec->handler_len = *p;
1996                                         ++p;
1997                                         tof_value = read32 (p);
1998                                         p += 4;
1999                                 }
2000                                 if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
2001                                         ec->data.filter_offset = tof_value;
2002                                 } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
2003                                         ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
2004                                 } else {
2005                                         ec->data.catch_class = NULL;
2006                                 }
2007                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
2008                         }
2009
2010                 }
2011                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
2012                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
2013                 else
2014                         return;
2015         }
2016 }
2017
2018 /*
2019  * mono_metadata_parse_mh:
2020  * @m: metadata context
2021  * @ptr: pointer to the method header.
2022  *
2023  * Decode the method header at @ptr, including pointer to the IL code,
2024  * info about local variables and optional exception tables.
2025  *
2026  * Returns: a MonoMethodHeader.
2027  */
2028 MonoMethodHeader *
2029 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, const char *ptr)
2030 {
2031         MonoMethodHeader *mh;
2032         unsigned char flags = *(const unsigned char *) ptr;
2033         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
2034         guint16 fat_flags;
2035         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
2036         const unsigned char *code;
2037         int hsize;
2038         
2039         g_return_val_if_fail (ptr != NULL, NULL);
2040
2041         switch (format){
2042         case METHOD_HEADER_TINY_FORMAT:
2043                 mh = g_new0 (MonoMethodHeader, 1);
2044                 ptr++;
2045                 mh->max_stack = 8;
2046                 local_var_sig_tok = 0;
2047                 mh->code_size = flags >> 2;
2048                 mh->code = ptr;
2049                 return mh;
2050         case METHOD_HEADER_TINY_FORMAT1:
2051                 mh = g_new0 (MonoMethodHeader, 1);
2052                 ptr++;
2053                 mh->max_stack = 8;
2054                 local_var_sig_tok = 0;
2055
2056                 /*
2057                  * The spec claims 3 bits, but the Beta2 is
2058                  * incorrect
2059                  */
2060                 mh->code_size = flags >> 2;
2061                 mh->code = ptr;
2062                 return mh;
2063         case METHOD_HEADER_FAT_FORMAT:
2064                 fat_flags = read16 (ptr);
2065                 ptr += 2;
2066                 hsize = (fat_flags >> 12) & 0xf;
2067                 max_stack = read16 (ptr);
2068                 ptr += 2;
2069                 code_size = read32 (ptr);
2070                 ptr += 4;
2071                 local_var_sig_tok = read32 (ptr);
2072                 ptr += 4;
2073
2074                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
2075                         init_locals = 1;
2076                 else
2077                         init_locals = 0;
2078
2079                 code = ptr;
2080
2081                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
2082                         break;
2083
2084                 /*
2085                  * There are more sections
2086                  */
2087                 ptr = code + code_size;
2088                 
2089                 break;
2090                 
2091         default:
2092                 return NULL;
2093         }
2094                        
2095         if (local_var_sig_tok) {
2096                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
2097                 const char *locals_ptr;
2098                 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
2099                 int len=0, i, bsize;
2100
2101                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
2102                 locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
2103                 bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
2104                 if (*locals_ptr != 0x07)
2105                         g_warning ("wrong signature for locals blob");
2106                 locals_ptr++;
2107                 len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
2108                 mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
2109                 mh->num_locals = len;
2110                 for (i = 0; i < len; ++i)
2111                         mh->locals [i] = mono_metadata_parse_type_full (
2112                                 m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
2113         } else {
2114                 mh = g_new0 (MonoMethodHeader, 1);
2115         }
2116         mh->code = code;
2117         mh->code_size = code_size;
2118         mh->max_stack = max_stack;
2119         mh->init_locals = init_locals;
2120         if (fat_flags & METHOD_HEADER_MORE_SECTS)
2121                 parse_section_data (m, mh, (const unsigned char*)ptr);
2122         return mh;
2123 }
2124
2125 MonoMethodHeader *
2126 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
2127 {
2128         return mono_metadata_parse_mh_full (m, NULL, ptr);
2129 }
2130
2131 /*
2132  * mono_metadata_free_mh:
2133  * @mh: a method header
2134  *
2135  * Free the memory allocated for the method header.
2136  */
2137 void
2138 mono_metadata_free_mh (MonoMethodHeader *mh)
2139 {
2140         int i;
2141         for (i = 0; i < mh->num_locals; ++i)
2142                 mono_metadata_free_type (mh->locals[i]);
2143         g_free (mh->clauses);
2144         g_free (mh);
2145 }
2146
2147 /**
2148  * mono_metadata_parse_field_type:
2149  * @m: metadata context to extract information from
2150  * @ptr: pointer to the field signature
2151  * @rptr: pointer updated to match the end of the decoded stream
2152  *
2153  * Parses the field signature, and returns the type information for it. 
2154  *
2155  * Returns: The MonoType that was extracted from @ptr.
2156  */
2157 MonoType *
2158 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
2159 {
2160         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
2161 }
2162
2163 /**
2164  * mono_metadata_parse_param:
2165  * @m: metadata context to extract information from
2166  * @ptr: pointer to the param signature
2167  * @rptr: pointer updated to match the end of the decoded stream
2168  *
2169  * Parses the param signature, and returns the type information for it. 
2170  *
2171  * Returns: The MonoType that was extracted from @ptr.
2172  */
2173 MonoType *
2174 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
2175 {
2176         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
2177 }
2178
2179 /*
2180  * mono_metadata_token_from_dor:
2181  * @dor_token: A TypeDefOrRef coded index
2182  *
2183  * dor_token is a TypeDefOrRef coded index: it contains either
2184  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
2185  * bits contain an index into the table.
2186  *
2187  * Returns: an expanded token
2188  */
2189 guint32
2190 mono_metadata_token_from_dor (guint32 dor_index)
2191 {
2192         guint32 table, idx;
2193
2194         table = dor_index & 0x03;
2195         idx = dor_index >> 2;
2196
2197         switch (table){
2198         case 0: /* TypeDef */
2199                 return MONO_TOKEN_TYPE_DEF | idx;
2200
2201         case 1: /* TypeRef */
2202                 return MONO_TOKEN_TYPE_REF | idx;
2203
2204         case 2: /* TypeSpec */
2205                 return MONO_TOKEN_TYPE_SPEC | idx;
2206
2207         default:
2208                 g_assert_not_reached ();
2209         }
2210
2211         return 0;
2212 }
2213
2214 /*
2215  * We use this to pass context information to the row locator
2216  */
2217 typedef struct {
2218         int idx;                        /* The index that we are trying to locate */
2219         int col_idx;            /* The index in the row where idx may be stored */
2220         MonoTableInfo *t;       /* pointer to the table */
2221         guint32 result;
2222 } locator_t;
2223
2224 /*
2225  * How the row locator works.
2226  *
2227  *   Table A
2228  *   ___|___
2229  *   ___|___         Table B
2230  *   ___|___------>  _______
2231  *   ___|___         _______
2232  *   
2233  * A column in the rows of table A references an index in table B.
2234  * For example A may be the TYPEDEF table and B the METHODDEF table.
2235  * 
2236  * Given an index in table B we want to get the row in table A
2237  * where the column n references our index in B.
2238  *
2239  * In the locator_t structure:
2240  *      t is table A
2241  *      col_idx is the column number
2242  *      index is the index in table B
2243  *      result will be the index in table A
2244  *
2245  * Examples:
2246  * Table A              Table B         column (in table A)
2247  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
2248  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
2249  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
2250  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
2251  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
2252  *
2253  * Note that we still don't support encoded indexes.
2254  *
2255  */
2256 static int
2257 typedef_locator (const void *a, const void *b)
2258 {
2259         locator_t *loc = (locator_t *) a;
2260         const char *bb = (const char *) b;
2261         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
2262         guint32 col, col_next;
2263
2264         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
2265
2266         if (loc->idx < col)
2267                 return -1;
2268
2269         /*
2270          * Need to check that the next row is valid.
2271          */
2272         if (typedef_index + 1 < loc->t->rows) {
2273                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
2274                 if (loc->idx >= col_next)
2275                         return 1;
2276
2277                 if (col == col_next)
2278                         return 1; 
2279         }
2280
2281         loc->result = typedef_index;
2282         
2283         return 0;
2284 }
2285
2286 static int
2287 table_locator (const void *a, const void *b)
2288 {
2289         locator_t *loc = (locator_t *) a;
2290         const char *bb = (const char *) b;
2291         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
2292         guint32 col;
2293         
2294         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
2295
2296         if (loc->idx == col) {
2297                 loc->result = table_index;
2298                 return 0;
2299         }
2300         if (loc->idx < col)
2301                 return -1;
2302         else 
2303                 return 1;
2304 }
2305
2306 static int
2307 declsec_locator (const void *a, const void *b)
2308 {
2309         locator_t *loc = (locator_t *) a;
2310         const char *bb = (const char *) b;
2311         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
2312         guint32 col;
2313
2314         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
2315
2316         if (loc->idx == col) {
2317                 loc->result = table_index;
2318                 return 0;
2319         }
2320         if (loc->idx < col)
2321                 return -1;
2322         else
2323                 return 1;
2324 }
2325
2326 /**
2327  * mono_metadata_typedef_from_field:
2328  * @meta: metadata context
2329  * @index: FieldDef token
2330  *
2331  * Returns: the 1-based index into the TypeDef table of the type that
2332  * declared the field described by @index, or 0 if not found.
2333  */
2334 guint32
2335 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
2336 {
2337         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
2338         locator_t loc;
2339
2340         if (!tdef->base)
2341                 return 0;
2342
2343         loc.idx = mono_metadata_token_index (index);
2344         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
2345         loc.t = tdef;
2346
2347         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
2348                 g_assert_not_reached ();
2349
2350         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2351         return loc.result + 1;
2352 }
2353
2354 /*
2355  * mono_metadata_typedef_from_method:
2356  * @meta: metadata context
2357  * @index: MethodDef token
2358  *
2359  * Returns: the 1-based index into the TypeDef table of the type that
2360  * declared the method described by @index.  0 if not found.
2361  */
2362 guint32
2363 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
2364 {
2365         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
2366         locator_t loc;
2367         
2368         if (!tdef->base)
2369                 return 0;
2370
2371         loc.idx = mono_metadata_token_index (index);
2372         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
2373         loc.t = tdef;
2374
2375         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
2376                 g_assert_not_reached ();
2377
2378         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2379         return loc.result + 1;
2380 }
2381
2382 /*
2383  * mono_metadata_interfaces_from_typedef:
2384  * @meta: metadata context
2385  * @index: typedef token
2386  * 
2387  * Returns: and array of interfaces that the @index typedef token implements.
2388  * The number of elemnts in the array is returned in @count.
2389  */
2390 MonoClass**
2391 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, guint *count, MonoGenericContext *context)
2392 {
2393         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
2394         locator_t loc;
2395         guint32 start, i;
2396         guint32 cols [MONO_INTERFACEIMPL_SIZE];
2397         MonoClass **result;
2398         
2399         *count = 0;
2400
2401         if (!tdef->base)
2402                 return NULL;
2403
2404         loc.idx = mono_metadata_token_index (index);
2405         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
2406         loc.t = tdef;
2407
2408         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2409                 return NULL;
2410
2411         start = loc.result;
2412         /*
2413          * We may end up in the middle of the rows... 
2414          */
2415         while (start > 0) {
2416                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
2417                         start--;
2418                 else
2419                         break;
2420         }
2421         result = NULL;
2422         i = 0;
2423         while (start < tdef->rows) {
2424                 mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE);
2425                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
2426                         break;
2427                 result = g_renew (MonoClass*, result, i + 1);
2428                 result [i] = mono_class_get_full (
2429                         meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
2430                 *count = ++i;
2431                 ++start;
2432         }
2433         return result;
2434 }
2435
2436 MonoClass**
2437 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
2438 {
2439         return mono_metadata_interfaces_from_typedef_full (meta, index, count, NULL);
2440 }
2441
2442 /*
2443  * mono_metadata_nested_in_typedef:
2444  * @meta: metadata context
2445  * @index: typedef token
2446  * 
2447  * Returns: the 1-based index into the TypeDef table of the type
2448  * where the type described by @index is nested.
2449  * Retruns 0 if @index describes a non-nested type.
2450  */
2451 guint32
2452 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
2453 {
2454         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
2455         locator_t loc;
2456         
2457         if (!tdef->base)
2458                 return 0;
2459
2460         loc.idx = mono_metadata_token_index (index);
2461         loc.col_idx = MONO_NESTED_CLASS_NESTED;
2462         loc.t = tdef;
2463
2464         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2465                 return 0;
2466
2467         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2468         return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
2469 }
2470
2471 /*
2472  * mono_metadata_nesting_typedef:
2473  * @meta: metadata context
2474  * @index: typedef token
2475  * 
2476  * Returns: the 1-based index into the TypeDef table of the first type
2477  * that is nested inside the type described by @index. The search starts at
2478  * @start_index.  returns 0 if no such type is found.
2479  */
2480 guint32
2481 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
2482 {
2483         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
2484         guint32 start;
2485         guint32 class_index = mono_metadata_token_index (index);
2486         
2487         if (!tdef->base)
2488                 return 0;
2489
2490         start = start_index;
2491
2492         while (start <= tdef->rows) {
2493                 if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
2494                         break;
2495                 else
2496                         start++;
2497         }
2498
2499         if (start > tdef->rows)
2500                 return 0;
2501         else
2502                 return start;
2503 }
2504
2505 /*
2506  * mono_metadata_packing_from_typedef:
2507  * @meta: metadata context
2508  * @index: token representing a type
2509  * 
2510  * Returns: the info stored in the ClassLAyout table for the given typedef token
2511  * into the @packing and @size pointers.
2512  * Returns 0 if the info is not found.
2513  */
2514 guint32
2515 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
2516 {
2517         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
2518         locator_t loc;
2519         guint32 cols [MONO_CLASS_LAYOUT_SIZE];
2520         
2521         if (!tdef->base)
2522                 return 0;
2523
2524         loc.idx = mono_metadata_token_index (index);
2525         loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
2526         loc.t = tdef;
2527
2528         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2529                 return 0;
2530
2531         mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
2532         if (packing)
2533                 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
2534         if (size)
2535                 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
2536
2537         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2538         return loc.result + 1;
2539 }
2540
2541 /*
2542  * mono_metadata_custom_attrs_from_index:
2543  * @meta: metadata context
2544  * @index: token representing the parent
2545  * 
2546  * Returns: the 1-based index into the CustomAttribute table of the first 
2547  * attribute which belongs to the metadata object described by @index.
2548  * Returns 0 if no such attribute is found.
2549  */
2550 guint32
2551 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
2552 {
2553         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2554         locator_t loc;
2555         
2556         if (!tdef->base)
2557                 return 0;
2558
2559         loc.idx = index;
2560         loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
2561         loc.t = tdef;
2562
2563         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2564                 return 0;
2565
2566         /* Find the first entry by searching backwards */
2567         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
2568                 loc.result --;
2569
2570         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2571         return loc.result + 1;
2572 }
2573
2574 /*
2575  * mono_metadata_declsec_from_index:
2576  * @meta: metadata context
2577  * @index: token representing the parent
2578  * 
2579  * Returns: the 0-based index into the DeclarativeSecurity table of the first 
2580  * attribute which belongs to the metadata object described by @index.
2581  * Returns -1 if no such attribute is found.
2582  */
2583 guint32
2584 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
2585 {
2586         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
2587         locator_t loc;
2588
2589         if (!tdef->base)
2590                 return -1;
2591
2592         loc.idx = index;
2593         loc.col_idx = MONO_DECL_SECURITY_PARENT;
2594         loc.t = tdef;
2595
2596         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
2597                 return -1;
2598
2599         /* Find the first entry by searching backwards */
2600         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
2601                 loc.result --;
2602
2603         return loc.result;
2604 }
2605
2606 #ifdef DEBUG
2607 static void
2608 mono_backtrace (int limit)
2609 {
2610         void *array[limit];
2611         char **names;
2612         int i;
2613         backtrace (array, limit);
2614         names = backtrace_symbols (array, limit);
2615         for (i =0; i < limit; ++i) {
2616                 g_print ("\t%s\n", names [i]);
2617         }
2618         g_free (names);
2619 }
2620 #endif
2621
2622 #ifndef __GNUC__
2623 /*#define __alignof__(a) sizeof(a)*/
2624 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
2625 #endif
2626
2627 /*
2628  * mono_type_size:
2629  * @t: the type to return the size of
2630  *
2631  * Returns: the number of bytes required to hold an instance of this
2632  * type in memory
2633  */
2634 int
2635 mono_type_size (MonoType *t, gint *align)
2636 {
2637         if (!t) {
2638                 *align = 1;
2639                 return 0;
2640         }
2641         if (t->byref) {
2642                 *align = __alignof__(gpointer);
2643                 return sizeof (gpointer);
2644         }
2645
2646         switch (t->type){
2647         case MONO_TYPE_VOID:
2648                 *align = 1;
2649                 return 0;
2650         case MONO_TYPE_BOOLEAN:
2651                 *align = __alignof__(gint8);
2652                 return 1;
2653         case MONO_TYPE_I1:
2654         case MONO_TYPE_U1:
2655                 *align = __alignof__(gint8);
2656                 return 1;
2657         case MONO_TYPE_CHAR:
2658         case MONO_TYPE_I2:
2659         case MONO_TYPE_U2:
2660                 *align = __alignof__(gint16);
2661                 return 2;               
2662         case MONO_TYPE_I4:
2663         case MONO_TYPE_U4:
2664                 *align = __alignof__(gint32);
2665                 return 4;
2666         case MONO_TYPE_R4:
2667                 *align = __alignof__(float);
2668                 return 4;
2669         case MONO_TYPE_I8:
2670         case MONO_TYPE_U8:
2671                 *align = __alignof__(gint64);
2672                 return 8;               
2673         case MONO_TYPE_R8:
2674                 *align = __alignof__(double);
2675                 return 8;               
2676         case MONO_TYPE_I:
2677         case MONO_TYPE_U:
2678                 *align = __alignof__(gpointer);
2679                 return sizeof (gpointer);
2680         case MONO_TYPE_STRING:
2681                 *align = __alignof__(gpointer);
2682                 return sizeof (gpointer);
2683         case MONO_TYPE_OBJECT:
2684                 *align = __alignof__(gpointer);
2685                 return sizeof (gpointer);
2686         case MONO_TYPE_VALUETYPE: {
2687                 if (t->data.klass->enumtype)
2688                         return mono_type_size (t->data.klass->enum_basetype, align);
2689                 else
2690                         return mono_class_value_size (t->data.klass, align);
2691         }
2692         case MONO_TYPE_CLASS:
2693         case MONO_TYPE_SZARRAY:
2694         case MONO_TYPE_PTR:
2695         case MONO_TYPE_FNPTR:
2696         case MONO_TYPE_ARRAY:
2697                 *align = __alignof__(gpointer);
2698                 return sizeof (gpointer);
2699         case MONO_TYPE_TYPEDBYREF:
2700                 return mono_class_value_size (mono_defaults.typed_reference_class, align);
2701         case MONO_TYPE_GENERICINST: {
2702                 MonoGenericClass *gclass = t->data.generic_class;
2703
2704                 g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
2705
2706                 if (gclass->container_class->valuetype) {
2707                         if (gclass->container_class->enumtype)
2708                                 return mono_type_size (gclass->container_class->enum_basetype, align);
2709                         else
2710                                 return mono_class_value_size (gclass->klass, align);
2711                 } else {
2712                         *align = __alignof__(gpointer);
2713                         return sizeof (gpointer);
2714                 }
2715         }
2716         case MONO_TYPE_VAR:
2717         case MONO_TYPE_MVAR:
2718                 *align = __alignof__(gpointer);
2719                 return sizeof (gpointer);
2720         default:
2721                 g_error ("mono_type_size: type 0x%02x unknown", t->type);
2722         }
2723         return 0;
2724 }
2725
2726 /*
2727  * mono_type_stack_size:
2728  * @t: the type to return the size it uses on the stack
2729  *
2730  * Returns: the number of bytes required to hold an instance of this
2731  * type on the runtime stack
2732  */
2733 int
2734 mono_type_stack_size (MonoType *t, gint *align)
2735 {
2736         int tmp;
2737
2738         g_assert (t != NULL);
2739
2740         if (!align)
2741                 align = &tmp;
2742
2743         if (t->byref) {
2744                 *align = __alignof__(gpointer);
2745                 return sizeof (gpointer);
2746         }
2747
2748         switch (t->type){
2749         case MONO_TYPE_BOOLEAN:
2750         case MONO_TYPE_CHAR:
2751         case MONO_TYPE_I1:
2752         case MONO_TYPE_U1:
2753         case MONO_TYPE_I2:
2754         case MONO_TYPE_U2:
2755         case MONO_TYPE_I4:
2756         case MONO_TYPE_U4:
2757         case MONO_TYPE_I:
2758         case MONO_TYPE_U:
2759         case MONO_TYPE_STRING:
2760         case MONO_TYPE_OBJECT:
2761         case MONO_TYPE_CLASS:
2762         case MONO_TYPE_SZARRAY:
2763         case MONO_TYPE_PTR:
2764         case MONO_TYPE_FNPTR:
2765         case MONO_TYPE_ARRAY:
2766                 *align = __alignof__(gpointer);
2767                 return sizeof (gpointer);
2768         case MONO_TYPE_TYPEDBYREF:
2769                 *align = __alignof__(gpointer);
2770                 return sizeof (gpointer) * 3;
2771         case MONO_TYPE_R4:
2772                 *align = __alignof__(float);
2773                 return sizeof (float);          
2774         case MONO_TYPE_I8:
2775         case MONO_TYPE_U8:
2776                 *align = __alignof__(gint64);
2777                 return sizeof (gint64);         
2778         case MONO_TYPE_R8:
2779                 *align = __alignof__(double);
2780                 return sizeof (double);
2781         case MONO_TYPE_VALUETYPE: {
2782                 guint32 size;
2783
2784                 if (t->data.klass->enumtype)
2785                         return mono_type_stack_size (t->data.klass->enum_basetype, align);
2786                 else {
2787                         size = mono_class_value_size (t->data.klass, align);
2788
2789                         *align = *align + __alignof__(gpointer) - 1;
2790                         *align &= ~(__alignof__(gpointer) - 1);
2791
2792                         size += sizeof (gpointer) - 1;
2793                         size &= ~(sizeof (gpointer) - 1);
2794
2795                         return size;
2796                 }
2797         }
2798         case MONO_TYPE_GENERICINST: {
2799                 MonoGenericClass *gclass = t->data.generic_class;
2800
2801                 g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
2802
2803                 if (gclass->container_class->valuetype) {
2804                         if (gclass->container_class->enumtype)
2805                                 return mono_type_stack_size (gclass->container_class->enum_basetype, align);
2806                         else {
2807                                 guint32 size = mono_class_value_size (gclass->klass, align);
2808
2809                                 *align = *align + __alignof__(gpointer) - 1;
2810                                 *align &= ~(__alignof__(gpointer) - 1);
2811
2812                                 size += sizeof (gpointer) - 1;
2813                                 size &= ~(sizeof (gpointer) - 1);
2814
2815                                 return size;
2816                         }
2817                 } else {
2818                         *align = __alignof__(gpointer);
2819                         return sizeof (gpointer);
2820                 }
2821         }
2822         default:
2823                 g_error ("type 0x%02x unknown", t->type);
2824         }
2825         return 0;
2826 }
2827
2828 gboolean
2829 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
2830 {
2831         return gclass->container_class->valuetype;
2832 }
2833
2834 static gboolean
2835 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
2836 {
2837         int i;
2838
2839         if ((g1->inst->type_argc != g2->inst->type_argc) || (g1->is_dynamic != g2->is_dynamic))
2840                 return FALSE;
2841         if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
2842                 return FALSE;
2843         for (i = 0; i < g1->inst->type_argc; ++i) {
2844                 if (!do_mono_metadata_type_equal (g1->inst->type_argv [i], g2->inst->type_argv [i], signature_only))
2845                         return FALSE;
2846         }
2847         return TRUE;
2848 }
2849
2850 guint
2851 mono_metadata_generic_method_hash (MonoGenericMethod *gmethod)
2852 {
2853         return gmethod->inst->id;
2854 }
2855
2856 gboolean
2857 mono_metadata_generic_method_equal (MonoGenericMethod *g1, MonoGenericMethod *g2)
2858 {
2859         return (g1->container == g2->container) && (g1->inst == g2->inst);
2860 }
2861
2862
2863 /*
2864  * mono_metadata_type_hash:
2865  * @t1: a type
2866  *
2867  * Computes an hash value for @t1 to be used in GHashTable.
2868  */
2869 guint
2870 mono_metadata_type_hash (MonoType *t1)
2871 {
2872         guint hash = t1->type;
2873
2874         hash |= t1->byref << 6; /* do not collide with t1->type values */
2875         switch (t1->type) {
2876         case MONO_TYPE_VALUETYPE:
2877         case MONO_TYPE_CLASS:
2878         case MONO_TYPE_SZARRAY:
2879                 /* check if the distribution is good enough */
2880                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
2881         case MONO_TYPE_PTR:
2882                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
2883         case MONO_TYPE_ARRAY:
2884                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
2885         case MONO_TYPE_GENERICINST:
2886                 return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
2887         }
2888         return hash;
2889 }
2890
2891 static gboolean
2892 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
2893 {
2894         if (p1 == p2)
2895                 return TRUE;
2896         if (p1->num != p2->num)
2897                 return FALSE;
2898
2899         g_assert (p1->owner && p2->owner);
2900         if (p1->owner == p2->owner)
2901                 return TRUE;
2902
2903         /*
2904          * If `signature_only' is true, we're comparing two (method) signatures.
2905          * In this case, the owner of two type parameters doesn't need to match.
2906          */
2907
2908         return signature_only;
2909 }
2910
2911 static gboolean
2912 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
2913 {
2914         if (c1 == c2)
2915                 return TRUE;
2916         if (c1->generic_class && c2->generic_class)
2917                 return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
2918         if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
2919                 return mono_metadata_generic_param_equal (
2920                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, FALSE);
2921         if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
2922                 return mono_metadata_generic_param_equal (
2923                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
2924         return FALSE;
2925 }
2926
2927 /*
2928  * mono_metadata_type_equal:
2929  * @t1: a type
2930  * @t2: another type
2931  *
2932  * Determine if @t1 and @t2 represent the same type.
2933  * Returns: #TRUE if @t1 and @t2 are equal.
2934  */
2935 static gboolean
2936 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
2937 {
2938         if (t1->type != t2->type ||
2939             t1->byref != t2->byref)
2940                 return FALSE;
2941
2942         switch (t1->type) {
2943         case MONO_TYPE_VOID:
2944         case MONO_TYPE_BOOLEAN:
2945         case MONO_TYPE_CHAR:
2946         case MONO_TYPE_I1:
2947         case MONO_TYPE_U1:
2948         case MONO_TYPE_I2:
2949         case MONO_TYPE_U2:
2950         case MONO_TYPE_I4:
2951         case MONO_TYPE_U4:
2952         case MONO_TYPE_I8:
2953         case MONO_TYPE_U8:
2954         case MONO_TYPE_R4:
2955         case MONO_TYPE_R8:
2956         case MONO_TYPE_STRING:
2957         case MONO_TYPE_I:
2958         case MONO_TYPE_U:
2959         case MONO_TYPE_OBJECT:
2960         case MONO_TYPE_TYPEDBYREF:
2961                 return TRUE;
2962         case MONO_TYPE_VALUETYPE:
2963         case MONO_TYPE_CLASS:
2964         case MONO_TYPE_SZARRAY:
2965                 return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
2966         case MONO_TYPE_PTR:
2967                 return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
2968         case MONO_TYPE_ARRAY:
2969                 if (t1->data.array->rank != t2->data.array->rank)
2970                         return FALSE;
2971                 return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
2972         case MONO_TYPE_GENERICINST:
2973                 return _mono_metadata_generic_class_equal (
2974                         t1->data.generic_class, t2->data.generic_class, signature_only);
2975         case MONO_TYPE_VAR:
2976                 return mono_metadata_generic_param_equal (
2977                         t1->data.generic_param, t2->data.generic_param, FALSE);
2978         case MONO_TYPE_MVAR:
2979                 return mono_metadata_generic_param_equal (
2980                         t1->data.generic_param, t2->data.generic_param, signature_only);
2981         default:
2982                 g_error ("implement type compare for %0x!", t1->type);
2983                 return FALSE;
2984         }
2985
2986         return FALSE;
2987 }
2988
2989 gboolean
2990 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
2991 {
2992         return do_mono_metadata_type_equal (t1, t2, FALSE);
2993 }
2994
2995 /**
2996  * mono_metadata_signature_equal:
2997  * @sig1: a signature
2998  * @sig2: another signature
2999  *
3000  * Determine if @sig1 and @sig2 represent the same signature, with the
3001  * same number of arguments and the same types.
3002  * Returns: #TRUE if @sig1 and @sig2 are equal.
3003  */
3004 gboolean
3005 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
3006 {
3007         int i;
3008
3009         if (sig1->hasthis != sig2->hasthis ||
3010             sig1->param_count != sig2->param_count)
3011                 return FALSE;
3012
3013         /*
3014          * We're just comparing the signatures of two methods here:
3015          *
3016          * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
3017          * U and V are equal here.
3018          *
3019          * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
3020          */
3021
3022         for (i = 0; i < sig1->param_count; i++) { 
3023                 MonoType *p1 = sig1->params[i];
3024                 MonoType *p2 = sig2->params[i];
3025                 
3026                 /* if (p1->attrs != p2->attrs)
3027                         return FALSE;
3028                 */
3029                 if (!do_mono_metadata_type_equal (p1, p2, TRUE))
3030                         return FALSE;
3031         }
3032
3033         if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
3034                 return FALSE;
3035         return TRUE;
3036 }
3037
3038 guint
3039 mono_signature_hash (MonoMethodSignature *sig)
3040 {
3041         guint i, res = sig->ret->type;
3042
3043         for (i = 0; i < sig->param_count; i++)
3044                 res = (res << 5) - res + sig->params[i]->type;
3045
3046         return res;
3047 }
3048
3049 /*
3050  * mono_metadata_encode_value:
3051  * @value: value to encode
3052  * @buf: buffer where to write the compressed representation
3053  * @endbuf: pointer updated to point at the end of the encoded output
3054  *
3055  * Encodes the value @value in the compressed representation used
3056  * in metadata and stores the result in @buf. @buf needs to be big
3057  * enough to hold the data (4 bytes).
3058  */
3059 void
3060 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
3061 {
3062         char *p = buf;
3063         
3064         if (value < 0x80)
3065                 *p++ = value;
3066         else if (value < 0x4000) {
3067                 p [0] = 0x80 | (value >> 8);
3068                 p [1] = value & 0xff;
3069                 p += 2;
3070         } else {
3071                 p [0] = (value >> 24) | 0xc0;
3072                 p [1] = (value >> 16) & 0xff;
3073                 p [2] = (value >> 8) & 0xff;
3074                 p [3] = value & 0xff;
3075                 p += 4;
3076         }
3077         if (endbuf)
3078                 *endbuf = p;
3079 }
3080
3081 /*
3082  * mono_metadata_field_info:
3083  * @meta: the Image the field is defined in
3084  * @index: the index in the field table representing the field
3085  * @offset: a pointer to an integer where to store the offset that 
3086  * may have been specified for the field in a FieldLayout table
3087  * @rva: a pointer to the RVA of the field data in the image that
3088  * may have been defined in a FieldRVA table
3089  * @marshal_spec: a pointer to the marshal spec that may have been 
3090  * defined for the field in a FieldMarshal table.
3091  *
3092  * Gather info for field @index that may have been defined in the FieldLayout, 
3093  * FieldRVA and FieldMarshal tables.
3094  * Either of offset, rva and marshal_spec can be NULL if you're not interested 
3095  * in the data.
3096  */
3097 void
3098 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
3099                           MonoMarshalSpec **marshal_spec)
3100 {
3101         MonoTableInfo *tdef;
3102         locator_t loc;
3103
3104         loc.idx = index + 1;
3105         if (offset) {
3106                 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
3107
3108                 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
3109                 loc.t = tdef;
3110
3111                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
3112                         *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
3113                 } else {
3114                         *offset = (guint32)-1;
3115                 }
3116         }
3117         if (rva) {
3118                 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
3119
3120                 loc.col_idx = MONO_FIELD_RVA_FIELD;
3121                 loc.t = tdef;
3122                 
3123                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
3124                         /*
3125                          * LAMESPEC: There is no signature, no nothing, just the raw data.
3126                          */
3127                         *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
3128                 } else {
3129                         *rva = 0;
3130                 }
3131         }
3132         if (marshal_spec) {
3133                 const char *p;
3134                 
3135                 if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
3136                         *marshal_spec = mono_metadata_parse_marshal_spec (meta, p);
3137                 }
3138         }
3139
3140 }
3141
3142 /*
3143  * mono_metadata_get_constant_index:
3144  * @meta: the Image the field is defined in
3145  * @index: the token that may have a row defined in the constants table
3146  * @hint: possible position for the row
3147  *
3148  * @token must be a FieldDef, ParamDef or PropertyDef token.
3149  *
3150  * Returns: the index into the Constants table or 0 if not found.
3151  */
3152 guint32
3153 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
3154 {
3155         MonoTableInfo *tdef;
3156         locator_t loc;
3157         guint32 index = mono_metadata_token_index (token);
3158
3159         tdef = &meta->tables [MONO_TABLE_CONSTANT];
3160         index <<= MONO_HASCONSTANT_BITS;
3161         switch (mono_metadata_token_table (token)) {
3162         case MONO_TABLE_FIELD:
3163                 index |= MONO_HASCONSTANT_FIEDDEF;
3164                 break;
3165         case MONO_TABLE_PARAM:
3166                 index |= MONO_HASCONSTANT_PARAM;
3167                 break;
3168         case MONO_TABLE_PROPERTY:
3169                 index |= MONO_HASCONSTANT_PROPERTY;
3170                 break;
3171         default:
3172                 g_warning ("Not a valid token for the constant table: 0x%08x", token);
3173                 return 0;
3174         }
3175         loc.idx = index;
3176         loc.col_idx = MONO_CONSTANT_PARENT;
3177         loc.t = tdef;
3178
3179         if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
3180                 return hint;
3181
3182         if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
3183                 return loc.result + 1;
3184         }
3185         return 0;
3186 }
3187
3188 /*
3189  * mono_metadata_events_from_typedef:
3190  * @meta: metadata context
3191  * @index: 0-based index (in the TypeDef table) describing a type
3192  *
3193  * Returns: the 0-based index in the Event table for the events in the
3194  * type. The last event that belongs to the type (plus 1) is stored
3195  * in the @end_idx pointer.
3196  */
3197 guint32
3198 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
3199 {
3200         locator_t loc;
3201         guint32 start, end;
3202         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_EVENTMAP];
3203
3204         *end_idx = 0;
3205         
3206         if (!tdef->base)
3207                 return 0;
3208
3209         loc.t = tdef;
3210         loc.col_idx = MONO_EVENT_MAP_PARENT;
3211         loc.idx = index + 1;
3212
3213         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3214                 return 0;
3215         
3216         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
3217         if (loc.result + 1 < tdef->rows) {
3218                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
3219         } else {
3220                 end = meta->tables [MONO_TABLE_EVENT].rows;
3221         }
3222
3223         *end_idx = end;
3224         return start - 1;
3225 }
3226
3227 /*
3228  * mono_metadata_methods_from_event:
3229  * @meta: metadata context
3230  * @index: 0-based index (in the Event table) describing a event
3231  *
3232  * Returns: the 0-based index in the MethodDef table for the methods in the
3233  * event. The last method that belongs to the event (plus 1) is stored
3234  * in the @end_idx pointer.
3235  */
3236 guint32
3237 mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_idx)
3238 {
3239         locator_t loc;
3240         guint start, end;
3241         guint32 cols [MONO_METHOD_SEMA_SIZE];
3242         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
3243
3244         *end_idx = 0;
3245         if (!msemt->base)
3246                 return 0;
3247
3248         loc.t = msemt;
3249         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
3250         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
3251
3252         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
3253                 return 0;
3254
3255         start = loc.result;
3256         /*
3257          * We may end up in the middle of the rows... 
3258          */
3259         while (start > 0) {
3260                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
3261                         start--;
3262                 else
3263                         break;
3264         }
3265         end = start + 1;
3266         while (end < msemt->rows) {
3267                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
3268                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
3269                         break;
3270                 ++end;
3271         }
3272         *end_idx = end;
3273         return start;
3274 }
3275
3276 /*
3277  * mono_metadata_properties_from_typedef:
3278  * @meta: metadata context
3279  * @index: 0-based index (in the TypeDef table) describing a type
3280  *
3281  * Returns: the 0-based index in the Property table for the properties in the
3282  * type. The last property that belongs to the type (plus 1) is stored
3283  * in the @end_idx pointer.
3284  */
3285 guint32
3286 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
3287 {
3288         locator_t loc;
3289         guint32 start, end;
3290         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_PROPERTYMAP];
3291
3292         *end_idx = 0;
3293         
3294         if (!tdef->base)
3295                 return 0;
3296
3297         loc.t = tdef;
3298         loc.col_idx = MONO_PROPERTY_MAP_PARENT;
3299         loc.idx = index + 1;
3300
3301         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3302                 return 0;
3303         
3304         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
3305         if (loc.result + 1 < tdef->rows) {
3306                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
3307         } else {
3308                 end = meta->tables [MONO_TABLE_PROPERTY].rows;
3309         }
3310
3311         *end_idx = end;
3312         return start - 1;
3313 }
3314
3315 /*
3316  * mono_metadata_methods_from_property:
3317  * @meta: metadata context
3318  * @index: 0-based index (in the PropertyDef table) describing a property
3319  *
3320  * Returns: the 0-based index in the MethodDef table for the methods in the
3321  * property. The last method that belongs to the property (plus 1) is stored
3322  * in the @end_idx pointer.
3323  */
3324 guint32
3325 mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *end_idx)
3326 {
3327         locator_t loc;
3328         guint start, end;
3329         guint32 cols [MONO_METHOD_SEMA_SIZE];
3330         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
3331
3332         *end_idx = 0;
3333         if (!msemt->base)
3334                 return 0;
3335
3336         loc.t = msemt;
3337         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
3338         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
3339
3340         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
3341                 return 0;
3342
3343         start = loc.result;
3344         /*
3345          * We may end up in the middle of the rows... 
3346          */
3347         while (start > 0) {
3348                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
3349                         start--;
3350                 else
3351                         break;
3352         }
3353         end = start + 1;
3354         while (end < msemt->rows) {
3355                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
3356                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
3357                         break;
3358                 ++end;
3359         }
3360         *end_idx = end;
3361         return start;
3362 }
3363
3364 guint32
3365 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
3366 {
3367         locator_t loc;
3368         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_IMPLMAP];
3369
3370         if (!tdef->base)
3371                 return 0;
3372
3373         loc.t = tdef;
3374         loc.col_idx = MONO_IMPLMAP_MEMBER;
3375         loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
3376
3377         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3378                 return 0;
3379
3380         return loc.result + 1;
3381 }
3382
3383 /**
3384  * @image: context where the image is created
3385  * @type_spec:  typespec token
3386  *
3387  * Creates a MonoType representing the TypeSpec indexed by the @type_spec
3388  * token.
3389  */
3390 MonoType *
3391 mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec)
3392 {
3393         guint32 idx = mono_metadata_token_index (type_spec);
3394         MonoTableInfo *t;
3395         guint32 cols [MONO_TYPESPEC_SIZE];       
3396         const char *ptr;
3397         guint32 len;
3398         MonoType *type;
3399
3400         mono_loader_lock ();
3401
3402         if ((type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)))) {
3403                 mono_loader_unlock ();
3404                 return type;
3405         }
3406
3407         t = &image->tables [MONO_TABLE_TYPESPEC];
3408         
3409         mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
3410         ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
3411         len = mono_metadata_decode_value (ptr, &ptr);
3412
3413         type = g_new0 (MonoType, 1);
3414
3415         g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
3416
3417         if (*ptr == MONO_TYPE_BYREF) {
3418                 type->byref = 1; 
3419                 ptr++;
3420         }
3421
3422         do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr);
3423
3424         mono_loader_unlock ();
3425
3426         return type;
3427 }
3428
3429 MonoType *
3430 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
3431 {
3432         return mono_type_create_from_typespec_full (image, NULL, type_spec);
3433 }
3434
3435 MonoMarshalSpec *
3436 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
3437 {
3438         MonoMarshalSpec *res;
3439         int len;
3440         const char *start = ptr;
3441
3442         /* fixme: this is incomplete, but I cant find more infos in the specs */
3443
3444         res = g_new0 (MonoMarshalSpec, 1);
3445         
3446         len = mono_metadata_decode_value (ptr, &ptr);
3447         res->native = *ptr++;
3448
3449         if (res->native == MONO_NATIVE_LPARRAY) {
3450                 if (ptr - start <= len)
3451                         res->data.array_data.elem_type = *ptr++;
3452                 if (ptr - start <= len)
3453                         res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
3454                 if (ptr - start <= len)
3455                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
3456         } 
3457
3458         if (res->native == MONO_NATIVE_BYVALTSTR) {
3459                 if (ptr - start <= len)
3460                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
3461         }
3462
3463         if (res->native == MONO_NATIVE_BYVALARRAY) {
3464                 if (ptr - start <= len)
3465                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
3466         }
3467         
3468         if (res->native == MONO_NATIVE_CUSTOM) {
3469                 /* skip unused type guid */
3470                 len = mono_metadata_decode_value (ptr, &ptr);
3471                 ptr += len;
3472                 /* skip unused native type name */
3473                 len = mono_metadata_decode_value (ptr, &ptr);
3474                 ptr += len;
3475                 /* read custom marshaler type name */
3476                 len = mono_metadata_decode_value (ptr, &ptr);
3477                 res->data.custom_data.custom_name = g_strndup (ptr, len);               
3478                 ptr += len;
3479                 /* read cookie string */
3480                 len = mono_metadata_decode_value (ptr, &ptr);
3481                 res->data.custom_data.cookie = g_strndup (ptr, len);
3482         }
3483
3484         return res;
3485 }
3486
3487 void 
3488 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
3489 {
3490         if (spec->native == MONO_NATIVE_CUSTOM) {
3491                 g_free (spec->data.custom_data.custom_name);
3492                 g_free (spec->data.custom_data.cookie);
3493         }
3494         g_free (spec);
3495 }
3496         
3497 guint32
3498 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
3499                         gboolean unicode, MonoMarshalConv *conv) 
3500 {
3501         MonoMarshalConv dummy_conv;
3502         int t = type->type;
3503
3504         if (!conv)
3505                 conv = &dummy_conv;
3506
3507         *conv = MONO_MARSHAL_CONV_NONE;
3508
3509         if (type->byref)
3510                 return MONO_NATIVE_UINT;
3511
3512 handle_enum:
3513         switch (t) {
3514         case MONO_TYPE_BOOLEAN: 
3515                 if (mspec) {
3516                         switch (mspec->native) {
3517                         case MONO_NATIVE_VARIANTBOOL:
3518                                 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
3519                                 return MONO_NATIVE_VARIANTBOOL;
3520                         case MONO_NATIVE_BOOLEAN:
3521                                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
3522                                 return MONO_NATIVE_BOOLEAN;
3523                         case MONO_NATIVE_I1:
3524                         case MONO_NATIVE_U1:
3525                                 return mspec->native;
3526                         default:
3527                                 g_error ("cant marshal bool to native type %02x", mspec->native);
3528                         }
3529                 }
3530                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
3531                 return MONO_NATIVE_BOOLEAN;
3532         case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
3533         case MONO_TYPE_I1: return MONO_NATIVE_I1;
3534         case MONO_TYPE_U1: return MONO_NATIVE_U1;
3535         case MONO_TYPE_I2: return MONO_NATIVE_I2;
3536         case MONO_TYPE_U2: return MONO_NATIVE_U2;
3537         case MONO_TYPE_I4: return MONO_NATIVE_I4;
3538         case MONO_TYPE_U4: return MONO_NATIVE_U4;
3539         case MONO_TYPE_I8: return MONO_NATIVE_I8;
3540         case MONO_TYPE_U8: return MONO_NATIVE_U8;
3541         case MONO_TYPE_R4: return MONO_NATIVE_R4;
3542         case MONO_TYPE_R8: return MONO_NATIVE_R8;
3543         case MONO_TYPE_STRING:
3544                 if (mspec) {
3545                         switch (mspec->native) {
3546                         case MONO_NATIVE_BSTR:
3547                                 *conv = MONO_MARSHAL_CONV_STR_BSTR;
3548                                 return MONO_NATIVE_BSTR;
3549                         case MONO_NATIVE_LPSTR:
3550                                 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
3551                                 return MONO_NATIVE_LPSTR;
3552                         case MONO_NATIVE_LPWSTR:
3553                                 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
3554                                 return MONO_NATIVE_LPWSTR;
3555                         case MONO_NATIVE_LPTSTR:
3556                                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
3557                                 return MONO_NATIVE_LPTSTR;
3558                         case MONO_NATIVE_ANSIBSTR:
3559                                 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
3560                                 return MONO_NATIVE_ANSIBSTR;
3561                         case MONO_NATIVE_TBSTR:
3562                                 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
3563                                 return MONO_NATIVE_TBSTR;
3564                         case MONO_NATIVE_BYVALTSTR:
3565                                 if (unicode)
3566                                         *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
3567                                 else
3568                                         *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
3569                                 return MONO_NATIVE_BYVALTSTR;
3570                         default:
3571                                 g_error ("cant marshal string to native type %02x", mspec->native);
3572                         }
3573                 }       
3574                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
3575                 return MONO_NATIVE_LPTSTR; 
3576         case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
3577         case MONO_TYPE_VALUETYPE: /*FIXME*/
3578                 if (type->data.klass->enumtype) {
3579                         t = type->data.klass->enum_basetype->type;
3580                         goto handle_enum;
3581                 }
3582                 return MONO_NATIVE_STRUCT;
3583         case MONO_TYPE_SZARRAY: 
3584         case MONO_TYPE_ARRAY: 
3585                 if (mspec) {
3586                         switch (mspec->native) {
3587                         case MONO_NATIVE_BYVALARRAY:
3588                                 *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
3589                                 return MONO_NATIVE_BYVALARRAY;
3590                         case MONO_NATIVE_SAFEARRAY:
3591                                 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
3592                                 return MONO_NATIVE_SAFEARRAY;
3593                         case MONO_NATIVE_LPARRAY:                               
3594                                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
3595                                 return MONO_NATIVE_LPARRAY;
3596                         default:
3597                                 g_error ("cant marshal array as native type %02x", mspec->native);
3598                         }
3599                 }       
3600
3601                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
3602                 return MONO_NATIVE_LPARRAY;
3603         case MONO_TYPE_I: return MONO_NATIVE_INT;
3604         case MONO_TYPE_U: return MONO_NATIVE_UINT;
3605         case MONO_TYPE_CLASS: 
3606         case MONO_TYPE_OBJECT: {
3607                 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
3608                 if (mspec) {
3609                         switch (mspec->native) {
3610                         case MONO_NATIVE_STRUCT:
3611                                 return MONO_NATIVE_STRUCT;
3612                         case MONO_NATIVE_INTERFACE:
3613                                 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
3614                                 return MONO_NATIVE_INTERFACE;
3615                         case MONO_NATIVE_IDISPATCH:
3616                                 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
3617                                 return MONO_NATIVE_IDISPATCH;
3618                         case MONO_NATIVE_IUNKNOWN:
3619                                 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
3620                                 return MONO_NATIVE_IUNKNOWN;
3621                         case MONO_NATIVE_FUNC:
3622                                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
3623                                                                                          type->data.klass == mono_defaults.delegate_class || 
3624                                                                                          type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
3625                                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
3626                                         return MONO_NATIVE_FUNC;
3627                                 }
3628                                 else
3629                                         /* Fall through */
3630                                         ;
3631                         default:
3632                                 g_error ("cant marshal object as native type %02x", mspec->native);
3633                         }
3634                 }
3635                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
3636                                              type->data.klass == mono_defaults.delegate_class || 
3637                                              type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
3638                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
3639                         return MONO_NATIVE_FUNC;
3640                 }
3641                 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
3642                 return MONO_NATIVE_STRUCT;
3643         }
3644         case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
3645         case MONO_TYPE_TYPEDBYREF:
3646         default:
3647                 g_error ("type 0x%02x not handled in marshal", t);
3648         }
3649         return MONO_NATIVE_MAX;
3650 }
3651
3652 const char*
3653 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
3654 {
3655         locator_t loc;
3656         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_FIELDMARSHAL];
3657
3658         if (!tdef->base)
3659                 return NULL;
3660
3661         loc.t = tdef;
3662         loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
3663         loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
3664
3665         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3666                 return NULL;
3667
3668         return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
3669 }
3670
3671 static MonoMethod*
3672 method_from_method_def_or_ref (MonoImage *m, guint32 tok)
3673 {
3674         guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
3675         switch (tok & MONO_METHODDEFORREF_MASK) {
3676         case MONO_METHODDEFORREF_METHODDEF:
3677                 return mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
3678         case MONO_METHODDEFORREF_METHODREF:
3679                 return mono_get_method (m, MONO_TOKEN_MEMBER_REF | idx, NULL);
3680         }
3681         g_assert_not_reached ();
3682         return NULL;
3683 }
3684
3685 MonoMethod**
3686 mono_class_get_overrides (MonoImage *image, guint32 type_token, gint32 *num_overrides)
3687 {
3688         locator_t loc;
3689         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
3690         guint32 start, end;
3691         gint32 i, num;
3692         guint32 cols [MONO_METHODIMPL_SIZE];
3693         MonoMethod **result;
3694
3695         if (num_overrides)
3696                 *num_overrides = 0;
3697
3698         if (!tdef->base)
3699                 return NULL;
3700
3701         loc.t = tdef;
3702         loc.col_idx = MONO_METHODIMPL_CLASS;
3703         loc.idx = mono_metadata_token_index (type_token);
3704
3705         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3706                 return NULL;
3707
3708         start = loc.result;
3709         end = start + 1;
3710         /*
3711          * We may end up in the middle of the rows... 
3712          */
3713         while (start > 0) {
3714                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
3715                         start--;
3716                 else
3717                         break;
3718         }
3719         while (end < tdef->rows) {
3720                 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
3721                         end++;
3722                 else
3723                         break;
3724         }
3725         num = end - start;
3726         result = g_new (MonoMethod*, num * 2);
3727         for (i = 0; i < num; ++i) {
3728                 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
3729                 result [i * 2] = method_from_method_def_or_ref (image, cols [MONO_METHODIMPL_DECLARATION]);
3730                 result [i * 2 + 1] = method_from_method_def_or_ref (image, cols [MONO_METHODIMPL_BODY]);
3731         }
3732
3733         if (num_overrides)
3734                 *num_overrides = num;
3735         return result;
3736 }
3737
3738 /**
3739  * mono_guid_to_string:
3740  *
3741  * Converts a 16 byte Microsoft GUID to the standard string representation.
3742  */
3743 char *
3744 mono_guid_to_string (const guint8 *guid)
3745 {
3746         return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
3747                                 guid[3], guid[2], guid[1], guid[0],
3748                                 guid[5], guid[4],
3749                                 guid[7], guid[6],
3750                                 guid[8], guid[9],
3751                                 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
3752 }
3753
3754 static MonoClass**
3755 get_constraints (MonoImage *image, int owner, MonoGenericContext *context)
3756 {
3757         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3758         guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
3759         guint32 i, token, found;
3760         MonoClass *klass, **res;
3761         GList *cons = NULL, *tmp;
3762         
3763
3764         found = 0;
3765         for (i = 0; i < tdef->rows; ++i) {
3766                 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
3767                 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
3768                         token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
3769                         klass = mono_class_get_full (image, token, context);
3770                         cons = g_list_append (cons, klass);
3771                         ++found;
3772                 } else {
3773                         /* contiguous list finished */
3774                         if (found)
3775                                 break;
3776                 }
3777         }
3778         if (!found)
3779                 return NULL;
3780         res = g_new0 (MonoClass*, found + 1);
3781         for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
3782                 res [i] = tmp->data;
3783         }
3784         g_list_free (cons);
3785         return res;
3786 }
3787
3788 MonoGenericContainer *
3789 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
3790 {
3791         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
3792         guint32 cols [MONO_GENERICPARAM_SIZE];
3793         guint32 i, owner = 0, last_num, n;
3794         MonoGenericContainer *container;
3795         MonoGenericClass *gclass;
3796         MonoGenericParam *params;
3797
3798         if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
3799                 owner = MONO_TYPEORMETHOD_TYPE;
3800         else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
3801                 owner = MONO_TYPEORMETHOD_METHOD;
3802         else {
3803                 g_error ("wrong token %x to load_generics_params", token);
3804                 return NULL;
3805         }
3806         owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
3807         if (!tdef->base)
3808                 return NULL;
3809
3810         for (i = 0; i < tdef->rows; ++i) {
3811                 mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
3812                 if (cols [MONO_GENERICPARAM_OWNER] == owner)
3813                         break;
3814         }
3815         last_num = i;
3816         if (i >= tdef->rows)
3817                 return NULL;
3818         params = NULL;
3819         n = 0;
3820         container = g_new0 (MonoGenericContainer, 1);
3821         do {
3822                 n++;
3823                 params = g_realloc (params, sizeof (MonoGenericParam) * n);
3824                 params [n - 1].owner = container;
3825                 params [n - 1].pklass = NULL;
3826                 params [n - 1].method = NULL;
3827                 params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS];
3828                 params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER];
3829                 params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
3830                 if (++i >= tdef->rows)
3831                         break;
3832                 mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
3833         } while (cols [MONO_GENERICPARAM_OWNER] == owner);
3834
3835         container->type_argc = n;
3836         container->type_params = params;
3837         container->parent = parent_container;
3838
3839         if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
3840                 container->is_method = 1;
3841
3842         container->context.container = container;
3843
3844         for (i = 0; i < n; i++)
3845                 params [i].constraints = get_constraints (image, last_num + i + 1, &container->context);
3846
3847         return container;
3848 }
3849
3850 gboolean
3851 mono_type_is_byref (MonoType *type)
3852 {
3853         return type->byref;
3854 }
3855
3856 int
3857 mono_type_get_type (MonoType *type)
3858 {
3859         return type->type;
3860 }
3861
3862 /* For MONO_TYPE_FNPTR */
3863 MonoMethodSignature*
3864 mono_type_get_signature (MonoType *type)
3865 {
3866         return type->data.method;
3867 }
3868
3869 /* For MONO_TYPE_CLASS, VALUETYPE */
3870 MonoClass*
3871 mono_type_get_class (MonoType *type)
3872 {
3873         return type->data.klass;
3874 }
3875
3876 /* For MONO_TYPE_ARRAY */
3877 MonoArrayType*
3878 mono_type_get_array_type (MonoType *type)
3879 {
3880         return type->data.array;
3881 }
3882
3883 MonoClass*
3884 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
3885 {
3886         /* FIXME: implement */
3887         return NULL;
3888 }
3889
3890 MonoType*
3891 mono_signature_get_return_type (MonoMethodSignature *sig)
3892 {
3893         return sig->ret;
3894 }
3895
3896 MonoType*
3897 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
3898 {
3899         MonoType** type;
3900         if (!iter)
3901                 return NULL;
3902         if (!*iter) {
3903                 /* start from the first */
3904                 if (sig->param_count) {
3905                         *iter = &sig->params [0];
3906                         return sig->params [0];
3907                 } else {
3908                         /* no method */
3909                         return NULL;
3910                 }
3911         }
3912         type = *iter;
3913         type++;
3914         if (type < &sig->params [sig->param_count]) {
3915                 *iter = type;
3916                 return *type;
3917         }
3918         return NULL;
3919 }
3920
3921 guint32
3922 mono_signature_get_param_count (MonoMethodSignature *sig)
3923 {
3924         return sig->param_count;
3925 }
3926
3927 guint32
3928 mono_signature_get_call_conv (MonoMethodSignature *sig)
3929 {
3930         return sig->call_convention;
3931 }
3932
3933 int
3934 mono_signature_vararg_start (MonoMethodSignature *sig)
3935 {
3936         return sig->sentinelpos;
3937 }
3938
3939 gboolean
3940 mono_signature_is_instance (MonoMethodSignature *sig)
3941 {
3942         return sig->hasthis;
3943 }
3944
3945 gboolean
3946 mono_signature_explicit_this (MonoMethodSignature *sig)
3947 {
3948         return sig->explicit_this;
3949 }
3950