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