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