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