2001-09-21 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / metadata / metadata.c
1 /*
2  * metadata.c: Routines for accessing the metadata
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <stdio.h> 
12 #include <stdlib.h>
13 #include <glib.h>
14 #include "metadata.h"
15 #include "tabledefs.h"
16 #include "endian.h"
17 #include "cil-coff.h"
18 #include "tokentype.h"
19 #include "private.h"
20 #include "class.h"
21
22 static void do_mono_metadata_parse_type (MonoType *type, MonoMetadata *m, const char *ptr, const char **rptr);
23
24 /*
25  * Encoding of the "description" argument:
26  *
27  * identifier [CODE ARG]
28  *
29  * If CODE is ':', then a lookup on table ARG is performed
30  * If CODE is '=', then a lookup in the aliased-table ARG is performed
31  * If CODE is '#', then this encodes a flag, ARG is the flag name. 
32  *
33  * Aliased table for example is `CustomAttributeType' which depending on the
34  * information might refer to different tables.
35  */
36
37 static MonoMetaTable AssemblySchema [] = {
38         { MONO_MT_UINT32,     "HashId" },
39         { MONO_MT_UINT16,     "Major" },  
40         { MONO_MT_UINT16,     "Minor" },
41         { MONO_MT_UINT16,     "BuildNumber" },
42         { MONO_MT_UINT16,     "RevisionNumber" },
43         { MONO_MT_UINT32,     "Flags" },
44         { MONO_MT_BLOB_IDX,   "PublicKey" },
45         { MONO_MT_STRING_IDX, "Name" },
46         { MONO_MT_STRING_IDX, "Culture" },
47         { MONO_MT_END, NULL }
48 };
49         
50 static MonoMetaTable AssemblyOSSchema [] = {
51         { MONO_MT_UINT32,     "OSPlatformID" },
52         { MONO_MT_UINT32,     "OSMajor" },
53         { MONO_MT_UINT32,     "OSMinor" },
54         { MONO_MT_END, NULL }
55 };
56
57 static MonoMetaTable AssemblyProcessorSchema [] = {
58         { MONO_MT_UINT32,     "Processor" },
59         { MONO_MT_END, NULL }
60 };
61
62 static MonoMetaTable AssemblyRefSchema [] = {
63         { MONO_MT_UINT16,     "Major" },
64         { MONO_MT_UINT16,     "Minor" },
65         { MONO_MT_UINT16,     "Build" },
66         { MONO_MT_UINT16,     "Revision" },
67         { MONO_MT_UINT32,     "Flags" },
68         { MONO_MT_BLOB_IDX,   "PublicKeyOrToken" },
69         { MONO_MT_STRING_IDX, "Name" },
70         { MONO_MT_STRING_IDX, "Culture" },
71         { MONO_MT_BLOB_IDX,   "HashValue" },
72         { MONO_MT_END, NULL }
73 };
74
75 static MonoMetaTable AssemblyRefOSSchema [] = {
76         { MONO_MT_UINT32,     "OSPlatformID" },
77         { MONO_MT_UINT32,     "OSMajorVersion" },
78         { MONO_MT_UINT32,     "OSMinorVersion" },
79         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
80         { MONO_MT_END, NULL }
81 };
82
83 static MonoMetaTable AssemblyRefProcessorSchema [] = {
84         { MONO_MT_UINT32,     "Processor" },
85         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
86         { MONO_MT_END, NULL }   
87 };
88
89 static MonoMetaTable ClassLayoutSchema [] = {
90         { MONO_MT_UINT16,     "PackingSize" },
91         { MONO_MT_UINT32,     "ClassSize" },
92         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
93         { MONO_MT_END, NULL }
94 };
95
96 static MonoMetaTable ConstantSchema [] = {
97         { MONO_MT_UINT8,      "Type" },
98         { MONO_MT_UINT8,      "PaddingZero" },
99         { MONO_MT_CONST_IDX,  "Parent" },
100         { MONO_MT_BLOB_IDX,   "Value" },
101         { MONO_MT_END, NULL }
102 };
103
104 static MonoMetaTable CustomAttributeSchema [] = {
105         { MONO_MT_HASCAT_IDX, "Parent" },
106         { MONO_MT_CAT_IDX,    "Type" },
107         { MONO_MT_BLOB_IDX,   "Value" },
108         { MONO_MT_END, NULL }
109 };
110
111 static MonoMetaTable DeclSecuritySchema [] = {
112         { MONO_MT_UINT16,     "Action" },
113         { MONO_MT_HASDEC_IDX, "Parent" },
114         { MONO_MT_BLOB_IDX,   "PermissionSet" },
115         { MONO_MT_END, NULL }   
116 };
117
118 static MonoMetaTable EventMapSchema [] = {
119         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
120         { MONO_MT_TABLE_IDX,  "EventList:Event" },
121         { MONO_MT_END, NULL }   
122 };
123
124 static MonoMetaTable EventSchema [] = {
125         { MONO_MT_UINT16,     "EventFlags#EventAttribute" },
126         { MONO_MT_STRING_IDX, "Name" },
127         { MONO_MT_TABLE_IDX,  "EventType" }, /* TypeDef or TypeRef */
128         { MONO_MT_END, NULL }   
129 };
130
131 static MonoMetaTable ExportedTypeSchema [] = {
132         { MONO_MT_UINT32,     "Flags" },
133         { MONO_MT_TABLE_IDX,  "TypeDefId" },
134         { MONO_MT_STRING_IDX, "TypeName" },
135         { MONO_MT_STRING_IDX, "TypeNameSpace" },
136         { MONO_MT_IMPL_IDX,   "Implementation" },
137         { MONO_MT_END, NULL }   
138 };
139
140 static MonoMetaTable FieldSchema [] = {
141         { MONO_MT_UINT16,     "Flags" },
142         { MONO_MT_STRING_IDX, "Name" },
143         { MONO_MT_BLOB_IDX,   "Signature" },
144         { MONO_MT_END, NULL }   
145 };
146 static MonoMetaTable FieldLayoutSchema [] = {
147         { MONO_MT_UINT32,     "Offset" },
148         { MONO_MT_TABLE_IDX,  "Field:Field" },
149         { MONO_MT_END, NULL }   
150 };
151
152 static MonoMetaTable FieldMarshalSchema [] = {
153         { MONO_MT_HFM_IDX,    "Parent" },
154         { MONO_MT_BLOB_IDX,   "NativeType" },
155         { MONO_MT_END, NULL }   
156 };
157 static MonoMetaTable FieldRVASchema [] = {
158         { MONO_MT_UINT32,     "RVA" },
159         { MONO_MT_TABLE_IDX,  "Field:Field" },
160         { MONO_MT_END, NULL }   
161 };
162
163 static MonoMetaTable FileSchema [] = {
164         { MONO_MT_UINT32,     "Flags" },
165         { MONO_MT_STRING_IDX, "Name" },
166         { MONO_MT_BLOB_IDX,   "Value" }, 
167         { MONO_MT_END, NULL }
168 };
169
170 static MonoMetaTable ImplMapSchema [] = {
171         { MONO_MT_UINT16,     "MappingFlag" },
172         { MONO_MT_MF_IDX,     "MemberForwarded" },
173         { MONO_MT_STRING_IDX, "ImportName" },
174         { MONO_MT_TABLE_IDX,  "ImportScope:ModuleRef" },
175         { MONO_MT_END, NULL }
176 };
177
178 static MonoMetaTable InterfaceImplSchema [] = {
179         { MONO_MT_TABLE_IDX,  "Class:TypeDef" }, 
180         { MONO_MT_TDOR_IDX,  "Interface=TypeDefOrRef" },
181         { MONO_MT_END, NULL }
182 };
183
184 static MonoMetaTable ManifestResourceSchema [] = {
185         { MONO_MT_UINT32,     "Offset" },
186         { MONO_MT_UINT32,     "Flags" },
187         { MONO_MT_STRING_IDX, "Name" },
188         { MONO_MT_IMPL_IDX,   "Implementation" },
189         { MONO_MT_END, NULL }
190 };
191
192 static MonoMetaTable MemberRefSchema [] = {
193         { MONO_MT_MRP_IDX,    "Class" },
194         { MONO_MT_STRING_IDX, "Name" },
195         { MONO_MT_BLOB_IDX,   "Signature" },
196         { MONO_MT_END, NULL }
197 };
198
199 static MonoMetaTable MethodSchema [] = {
200         { MONO_MT_UINT32,     "RVA" },
201         { MONO_MT_UINT16,     "ImplFlags#MethodImplAttributes" },
202         { MONO_MT_UINT16,     "Flags#MethodAttribute" },
203         { MONO_MT_STRING_IDX, "Name" },
204         { MONO_MT_BLOB_IDX,   "Signature" },
205         { MONO_MT_TABLE_IDX,  "ParamList:Param" },
206         { MONO_MT_END, NULL }
207 };
208
209 static MonoMetaTable MethodImplSchema [] = {
210         { MONO_MT_TABLE_IDX,  "Class:TypeDef" },
211         { MONO_MT_MDOR_IDX,   "MethodBody" },
212         { MONO_MT_MDOR_IDX,   "MethodDeclaration" },
213         { MONO_MT_END, NULL }
214 };
215
216 static MonoMetaTable MethodSemanticsSchema [] = {
217         { MONO_MT_UINT16,     "MethodSemantic" },
218         { MONO_MT_TABLE_IDX,  "Method:Method" },
219         { MONO_MT_HS_IDX,     "Association" },
220         { MONO_MT_END, NULL }
221 };
222
223 static MonoMetaTable ModuleSchema [] = {
224         { MONO_MT_UINT16,     "Generation" },
225         { MONO_MT_STRING_IDX, "Name" },
226         { MONO_MT_GUID_IDX,   "MVID" },
227         { MONO_MT_GUID_IDX,   "EncID" },
228         { MONO_MT_GUID_IDX,   "EncBaseID" },
229         { MONO_MT_END, NULL }
230 };
231
232 static MonoMetaTable ModuleRefSchema [] = {
233         { MONO_MT_STRING_IDX, "Name" },
234         { MONO_MT_END, NULL }
235 };
236
237 static MonoMetaTable NestedClassSchema [] = {
238         { MONO_MT_TABLE_IDX,  "NestedClass:TypeDef" },
239         { MONO_MT_TABLE_IDX,  "EnclosingClass:TypeDef" },
240         { MONO_MT_END, NULL }
241 };
242
243 static MonoMetaTable ParamSchema [] = {
244         { MONO_MT_UINT16,     "Flags" },
245         { MONO_MT_UINT16,     "Sequence" },
246         { MONO_MT_STRING_IDX, "Name" },
247         { MONO_MT_END, NULL }   
248 };
249
250 static MonoMetaTable PropertySchema [] = {
251         { MONO_MT_UINT16,     "Flags" },
252         { MONO_MT_STRING_IDX, "Name" },
253         { MONO_MT_BLOB_IDX,   "Type" },
254         { MONO_MT_END, NULL }   
255 };
256
257 static MonoMetaTable PropertyMapSchema [] = {
258         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
259         { MONO_MT_TABLE_IDX,  "PropertyList:Property" },
260         { MONO_MT_END, NULL }
261 };
262
263 static MonoMetaTable StandaloneSigSchema [] = {
264         { MONO_MT_BLOB_IDX,   "Signature" },
265         { MONO_MT_END, NULL }
266 };
267
268 static MonoMetaTable TypeDefSchema [] = {
269         { MONO_MT_UINT32,     "Flags" },
270         { MONO_MT_STRING_IDX, "Name" },
271         { MONO_MT_STRING_IDX, "Namespace" },
272         { MONO_MT_TDOR_IDX,   "Extends" },
273         { MONO_MT_TABLE_IDX,  "FieldList:Field" },
274         { MONO_MT_TABLE_IDX,  "MethodList:Method" },
275         { MONO_MT_END, NULL }
276 };
277
278 static MonoMetaTable TypeRefSchema [] = {
279         { MONO_MT_RS_IDX,     "ResolutionScope=ResolutionScope" },
280         { MONO_MT_STRING_IDX, "Name" },
281         { MONO_MT_STRING_IDX, "Namespace" },
282         { MONO_MT_END, NULL }
283 };
284
285 static MonoMetaTable TypeSpecSchema [] = {
286         { MONO_MT_BLOB_IDX,   "Signature" },
287         { MONO_MT_END, NULL }
288 };
289
290 static struct {
291         MonoMetaTable *table;
292         const char    *name;
293 } tables [] = {
294         /*  0 */ { ModuleSchema,               "Module" },
295         /*  1 */ { TypeRefSchema,              "TypeRef" },
296         /*  2 */ { TypeDefSchema,              "TypeDef" },
297         /*  3 */ { NULL,                       NULL },
298         /*  4 */ { FieldSchema,                "Field" },
299         /*  5 */ { NULL,                       NULL },
300         /*  6 */ { MethodSchema,               "Method" },
301         /*  7 */ { NULL,                       NULL },
302         /*  8 */ { ParamSchema,                "Param" },
303         /*  9 */ { InterfaceImplSchema,        "InterfaceImpl" },
304         /*  A */ { MemberRefSchema,            "MemberRef" },
305         /*  B */ { ConstantSchema,             "Constant" },
306         /*  C */ { CustomAttributeSchema,      "CustomAttribute" },
307         /*  D */ { FieldMarshalSchema,         "FieldMarshal" },
308         /*  E */ { DeclSecuritySchema,         "DeclSecurity" },
309         /*  F */ { ClassLayoutSchema,          "ClassLayout" },
310         /* 10 */ { FieldLayoutSchema,          "FieldLayout" },
311         /* 11 */ { StandaloneSigSchema,        "StandaloneSig" },
312         /* 12 */ { EventMapSchema,             "EventMap" },
313         /* 13 */ { NULL,                       NULL },
314         /* 14 */ { EventSchema,                "Event" },
315         /* 15 */ { PropertyMapSchema,          "PropertyMap" },
316         /* 16 */ { NULL,                       NULL },
317         /* 17 */ { PropertySchema,             "PropertyTable" },
318         /* 18 */ { MethodSemanticsSchema,      "MethodSemantics" },
319         /* 19 */ { MethodImplSchema,           "MethodImpl" },
320         /* 1A */ { ModuleRefSchema,            "ModuleRef" },
321         /* 1B */ { TypeSpecSchema,             "TypeSpec" },
322         /* 1C */ { ImplMapSchema,              "ImplMap" },
323         /* 1D */ { FieldRVASchema,             "FieldRVA" },
324         /* 1E */ { NULL,                       NULL },
325         /* 1F */ { NULL,                       NULL },
326         /* 20 */ { AssemblySchema,             "Assembly" },
327         /* 21 */ { AssemblyProcessorSchema,    "AssemblyProcessor" },
328         /* 22 */ { AssemblyOSSchema,           "AssemblyOS" },
329         /* 23 */ { AssemblyRefSchema,          "AssemblyRef" },
330         /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" },
331         /* 25 */ { AssemblyRefOSSchema,        "AssemblyRefOS" },
332         /* 26 */ { FileSchema,                 "File" },
333         /* 27 */ { ExportedTypeSchema,         "ExportedType" },
334         /* 28 */ { ManifestResourceSchema,     "ManifestResource" },
335         /* 29 */ { NestedClassSchema,          "NestedClass" },
336         /* 2A */ { NULL,                       NULL },
337         /* 2B */ { NULL,                       NULL },
338 };
339
340 /**
341  * mono_meta_table_name:
342  * @table: table index
343  *
344  * Returns the name for the @table index
345  */
346 const char *
347 mono_meta_table_name (int table)
348 {
349         if ((table < 0) || (table > 0x29))
350                 return "";
351         
352         return tables [table].name;
353 }
354
355 /* The guy who wrote the spec for this should not be allowed near a
356  * computer again.
357  
358 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
359 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
360 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
361 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
362 inverse of this mapping.
363
364  */
365 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
366 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
367
368 /* Reference: Partition II - 23.2.6 */
369 static int
370 compute_size (MonoMetadata *meta, MonoMetaTable *table, int tableindex, guint32 *result_bitfield)
371 {
372         guint32 bitfield = 0;
373         int size = 0, field_size;
374         int i, n, code;
375         int shift = 0;
376
377         for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
378                 switch (code){
379                 case MONO_MT_UINT32:
380                         field_size = 4; break;
381                         
382                 case MONO_MT_UINT16:
383                         field_size = 2; break;
384                         
385                 case MONO_MT_UINT8:
386                         field_size = 1; break;
387                         
388                 case MONO_MT_BLOB_IDX:
389                         field_size = meta->idx_blob_wide ? 4 : 2; break;
390                         
391                 case MONO_MT_STRING_IDX:
392                         field_size = meta->idx_string_wide ? 4 : 2; break;
393                         
394                 case MONO_MT_GUID_IDX:
395                         field_size = meta->idx_guid_wide ? 4 : 2; break;
396
397                 case MONO_MT_TABLE_IDX:
398                         /* Uhm, a table index can point to other tables besides the current one
399                          * so, it's not correct to use the rowcount of the current table to
400                          * get the size for this column - lupus 
401                          */
402                         switch (tableindex) {
403                         case MONO_TABLE_ASSEMBLYREFOS:
404                                 g_assert (i == 3);
405                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
406                         case MONO_TABLE_ASSEMBLYPROCESSOR:
407                                 g_assert (i == 1);
408                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
409                         case MONO_TABLE_CLASSLAYOUT:
410                                 g_assert (i == 2);
411                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
412                         case MONO_TABLE_EVENTMAP:
413                                 g_assert (i == 0 || i == 1);
414                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
415                                         idx_size(MONO_TABLE_TYPEDEF); 
416                                 break;
417                         case MONO_TABLE_EVENT:
418                                 g_assert (i == 2);
419                                 field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
420                                 field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
421                                 break;
422                         case MONO_TABLE_EXPORTEDTYPE:
423                                 g_assert (i == 1);
424                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
425                         case MONO_TABLE_FIELDLAYOUT:
426                                 g_assert (i == 1);
427                                 field_size = idx_size (MONO_TABLE_FIELD); break;
428                         case MONO_TABLE_FIELDRVA:
429                                 g_assert (i == 1);
430                                 field_size = idx_size (MONO_TABLE_FIELD); break;
431                         case MONO_TABLE_IMPLMAP:
432                                 g_assert (i == 3);
433                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
434                         case MONO_TABLE_INTERFACEIMPL:
435                                 g_assert (i == 0);
436                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
437                         case MONO_TABLE_METHOD:
438                                 g_assert (i == 5);
439                                 field_size = idx_size (MONO_TABLE_PARAM); break;
440                         case MONO_TABLE_METHODIMPL:
441                                 g_assert (i == 0);
442                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
443                         case MONO_TABLE_METHODSEMANTICS:
444                                 g_assert (i == 1);
445                                 field_size = idx_size (MONO_TABLE_METHOD); break;
446                         case MONO_TABLE_NESTEDCLASS:
447                                 g_assert (i == 0 || i == 1);
448                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
449                         case MONO_TABLE_PROPERTYMAP:
450                                 g_assert (i == 0 || i == 1);
451                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
452                                         idx_size(MONO_TABLE_TYPEDEF); 
453                                 break;
454                         case MONO_TABLE_TYPEDEF:
455                                 g_assert (i == 4 || i == 5);
456                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
457                                         idx_size(MONO_TABLE_METHOD); 
458                                 break;
459                         default:
460                                 g_assert_not_reached ();
461                         }
462                         if (field_size != idx_size (tableindex))
463                                 g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
464                         
465                         break;
466
467                         /*
468                          * HasConstant: ParamDef, FieldDef, Property
469                          */
470                 case MONO_MT_CONST_IDX:
471                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
472                                  meta->tables [MONO_TABLE_FIELD].rows);
473                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
474
475                         /* 2 bits to encode tag */
476                         field_size = rtsize (n, 16-2);
477                         break;
478
479                         /*
480                          * HasCustomAttribute: points to any table but
481                          * itself.
482                          */
483                 case MONO_MT_HASCAT_IDX:
484                         /*
485                          * We believe that since the signature and
486                          * permission are indexing the Blob heap,
487                          * we should consider the blob size first
488                          */
489                         /* I'm not a believer - lupus
490                         if (meta->idx_blob_wide){
491                                 field_size = 4;
492                                 break;
493                         }*/
494                         
495                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
496                                  meta->tables [MONO_TABLE_FIELD].rows);
497                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
498                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
499                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
500                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
501                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
502                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
503                         /* Permission seems to be a blob heap pointer */
504                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
505                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
506                         /* Signature seems to be a blob heap pointer */
507                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
508                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
509                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
510                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
511                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
512                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
513                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
514
515                         /* 5 bits to encode */
516                         field_size = rtsize (n, 16-5);
517                         break;
518
519                         /*
520                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
521                          * MemberRef and String.  
522                          */
523                 case MONO_MT_CAT_IDX:
524                         /* String is a heap, if it is wide, we know the size */
525                         /* See above, nope. 
526                         if (meta->idx_string_wide){
527                                 field_size = 4;
528                                 break;
529                         }*/
530                         
531                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
532                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
533                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
534                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
535
536                         /* 3 bits to encode */
537                         field_size = rtsize (n, 16-3);
538                         break;
539
540                         /*
541                          * HasDeclSecurity: Typedef, MethodDef, Assembly
542                          */
543                 case MONO_MT_HASDEC_IDX:
544                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
545                                  meta->tables [MONO_TABLE_METHOD].rows);
546                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
547
548                         /* 2 bits to encode */
549                         field_size = rtsize (n, 16-2);
550                         break;
551
552                         /*
553                          * Implementation: File, AssemblyRef, ExportedType
554                          */
555                 case MONO_MT_IMPL_IDX:
556                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
557                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
558                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
559
560                         /* 2 bits to encode tag */
561                         field_size = rtsize (n, 16-2);
562                         break;
563
564                         /*
565                          * HasFieldMarshall: FieldDef, ParamDef
566                          */
567                 case MONO_MT_HFM_IDX:
568                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
569                                  meta->tables [MONO_TABLE_PARAM].rows);
570
571                         /* 1 bit used to encode tag */
572                         field_size = rtsize (n, 16-1);
573                         break;
574
575                         /*
576                          * MemberForwarded: FieldDef, MethodDef
577                          */
578                 case MONO_MT_MF_IDX:
579                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
580                                  meta->tables [MONO_TABLE_METHOD].rows);
581
582                         /* 1 bit used to encode tag */
583                         field_size = rtsize (n, 16-1);
584                         break;
585
586                         /*
587                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
588                          * LAMESPEC
589                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
590                          */
591                 case MONO_MT_TDOR_IDX:
592                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
593                                  meta->tables [MONO_TABLE_TYPEREF].rows);
594                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
595
596                         /* 2 bits to encode */
597                         field_size = rtsize (n, 16-2);
598                         break;
599
600                         /*
601                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
602                          */
603                 case MONO_MT_MRP_IDX:
604                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
605                                  meta->tables [MONO_TABLE_TYPEREF].rows);
606                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
607                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
608                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
609                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
610
611                         /* 3 bits to encode */
612                         field_size = rtsize (n, 16 - 3);
613                         break;
614                         
615                 case MONO_MT_MDOR_IDX:
616
617                         /*
618                          * MethodDefOrRef: MethodDef, MemberRef
619                          */
620                 case MONO_MT_HS_IDX:
621                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
622                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
623
624                         /* 1 bit used to encode tag */
625                         field_size = rtsize (n, 16-1);
626                         break;
627
628                         /*
629                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
630                          */
631                 case MONO_MT_RS_IDX:
632                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
633                                  meta->tables [MONO_TABLE_MODULEREF].rows);
634                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
635                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
636
637                         /* 2 bits used to encode tag (ECMA spec claims 3) */
638                         field_size = rtsize (n, 16 - 2);
639                         break;
640                 }
641
642                 /*
643                  * encode field size as follows (we just need to
644                  * distinguish them).
645                  *
646                  * 4 -> 3
647                  * 2 -> 1
648                  * 1 -> 0
649                  */
650                 bitfield |= (field_size-1) << shift;
651                 shift += 2;
652                 size += field_size;
653                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
654         }
655
656         *result_bitfield = (i << 24) | bitfield;
657         return size;
658 }
659
660 /**
661  * mono_metadata_compute_table_bases:
662  * @meta: metadata context to compute table values
663  *
664  * Computes the table bases for the metadata structure.
665  * This is an internal function used by the image loader code.
666  */
667 void
668 mono_metadata_compute_table_bases (MonoMetadata *meta)
669 {
670         int i;
671         char *base = meta->tables_base;
672         
673         for (i = 0; i < 64; i++){
674                 if (meta->tables [i].rows == 0)
675                         continue;
676
677                 meta->tables [i].row_size = compute_size (
678                         meta, tables [i].table, i,
679                         &meta->tables [i].size_bitfield);
680                 meta->tables [i].base = base;
681                 base += meta->tables [i].rows * meta->tables [i].row_size;
682         }
683 }
684
685 /**
686  * mono_metadata_locate:
687  * @meta: metadata context
688  * @table: table code.
689  * @idx: index of element to retrieve from @table.
690  *
691  * Returns a pointer to the @idx element in the metadata table
692  * whose code is @table.
693  */
694 char *
695 mono_metadata_locate (MonoMetadata *meta, int table, int idx)
696 {
697         /* idx == 0 refers always to NULL */
698         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
699            
700         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
701 }
702
703 char *
704 mono_metadata_locate_token (MonoMetadata *meta, guint32 token)
705 {
706         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
707 }
708
709 /**
710  * mono_metadata_get_table:
711  * @table: table to retrieve
712  *
713  * Returns the MonoMetaTable structure for table @table
714  */
715 MonoMetaTable *
716 mono_metadata_get_table (MonoMetaTableEnum table)
717 {
718         int x = (int) table;
719
720         g_return_val_if_fail ((x > 0) && (x <= MONO_TABLE_LAST), NULL);
721
722         return tables [table].table;
723 }
724
725 /**
726  * mono_metadata_string_heap:
727  * @meta: metadata context
728  * @index: index into the string heap.
729  *
730  * Returns: an in-memory pointer to the @index in the string heap.
731  */
732 const char *
733 mono_metadata_string_heap (MonoMetadata *meta, guint32 index)
734 {
735         g_return_val_if_fail (index < meta->heap_strings.size, "");
736         return meta->raw_metadata + meta->heap_strings.offset + index;
737 }
738
739 const char *
740 mono_metadata_user_string (MonoMetadata *meta, guint32 index)
741 {
742         g_return_val_if_fail (index < meta->heap_us.size, "");
743         return meta->raw_metadata + meta->heap_us.offset + index;
744 }
745
746 /**
747  * mono_metadata_blob_heap:
748  * @meta: metadata context
749  * @index: index into the blob.
750  *
751  * Returns: an in-memory pointer to the @index in the Blob heap.
752  */
753 const char *
754 mono_metadata_blob_heap (MonoMetadata *meta, guint32 index)
755 {
756         g_return_val_if_fail (index < meta->heap_blob.size, "");
757         return meta->raw_metadata + meta->heap_blob.offset + index;
758 }
759
760 static const char *
761 dword_align (const char *ptr)
762 {
763         return (const char *) (((guint32) (ptr + 3)) & ~3);
764 }
765
766 /**
767  * mono_metadata_decode_row:
768  * @t: table to extract information from.
769  * @idx: index in table.
770  * @res: array of @res_size cols to store the results in
771  *
772  * This decompresses the metadata element @idx in table @t
773  * into the guint32 @res array that has res_size elements
774  */
775 void
776 mono_metadata_decode_row (MonoTableInfo *t, int idx, guint32 *res, int res_size)
777 {
778         guint32 bitfield = t->size_bitfield;
779         int i, count = mono_metadata_table_count (bitfield);
780         char *data = t->base + idx * t->row_size;
781         
782         g_assert (res_size == count);
783         
784         for (i = 0; i < count; i++){
785                 int n = mono_metadata_table_size (bitfield, i);
786
787                 switch (n){
788                 case 1:
789                         res [i] = *data; break;
790                 case 2:
791                         res [i] = read16 (data); break;
792                         
793                 case 4:
794                         res [i] = read32 (data); break;
795                         
796                 default:
797                         g_assert_not_reached ();
798                 }
799                 data += n;
800         }
801 }
802
803 /**
804  * mono_metadata_decode_row_col:
805  * @t: table to extract information from.
806  * @idx: index for row in table.
807  * @col: column in the row.
808  *
809  * This function returns the value of column @col from the @idx
810  * row in the table @t.
811  */
812 guint32
813 mono_metadata_decode_row_col (MonoTableInfo *t, int idx, guint col)
814 {
815         guint32 bitfield = t->size_bitfield;
816         int i;
817         register char *data = t->base + idx * t->row_size;
818         register int n;
819         
820         g_assert (col < mono_metadata_table_count (bitfield));
821
822         n = mono_metadata_table_size (bitfield, 0);
823         for (i = 0; i < col; ++i) {
824                 data += n;
825                 n = mono_metadata_table_size (bitfield, i + 1);
826         }
827         switch (n){
828         case 1:
829                 return *data;
830         case 2:
831                 return read16 (data);
832         case 4:
833                 return read32 (data);
834         default:
835                 g_assert_not_reached ();
836         }
837         return 0;
838 }
839 /**
840  * mono_metadata_decode_blob_size:
841  * @ptr: pointer to a blob object
842  * @rptr: the new position of the pointer
843  *
844  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
845  *
846  * Returns: the size of the blob object
847  */
848 guint32
849 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
850 {
851         const unsigned char *ptr = (const unsigned char *)xptr;
852         guint32 size;
853         
854         if ((*ptr & 0x80) == 0){
855                 size = ptr [0] & 0x7f;
856                 ptr++;
857         } else if ((*ptr & 0x40) == 0){
858                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
859                 ptr += 2;
860         } else {
861                 size = ((ptr [0] & 0x1f) << 24) +
862                         (ptr [1] << 16) +
863                         (ptr [2] << 8) +
864                         ptr [3];
865                 ptr += 4;
866         }
867         if (rptr)
868                 *rptr = ptr;
869         return size;
870 }
871
872
873 /**
874  * mono_metadata_decode_value:
875  * @ptr: pointer to decode from
876  * @rptr: the new position of the pointer
877  *
878  * This routine decompresses 32-bit values as specified in the "Blob and
879  * Signature" section (22.2)
880  *
881  * Returns: the decoded value
882  */
883 guint32
884 mono_metadata_decode_value (const char *_ptr, const char **rptr)
885 {
886         const unsigned char *ptr = (unsigned char *) _ptr;
887         unsigned char b = *ptr;
888         guint32 len;
889         
890         if ((b & 0x80) == 0){
891                 len = b;
892                 ++ptr;
893         } else if ((b & 0x40) == 0){
894                 len = ((b & 0x3f) << 8 | ptr [1]);
895                 ptr += 2;
896         } else {
897                 len = ((b & 0x1f) << 24) |
898                         (ptr [1] << 16) |
899                         (ptr [2] << 8) |
900                         ptr [3];
901                 ptr += 4;
902         }
903         if (rptr)
904                 *rptr = ptr;
905         
906         return len;
907 }
908
909 guint32
910 mono_metadata_parse_typedef_or_ref (MonoMetadata *m, const char *ptr, const char **rptr)
911 {
912         guint32 token;
913         token = mono_metadata_decode_value (ptr, &ptr);
914         if (rptr)
915                 *rptr = ptr;
916         return mono_metadata_token_from_dor (token);
917 }
918
919 int
920 mono_metadata_parse_custom_mod (MonoMetadata *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
921 {
922         MonoCustomMod local;
923         if ((*ptr == MONO_TYPE_CMOD_OPT) ||
924             (*ptr == MONO_TYPE_CMOD_REQD)) {
925                 if (!dest)
926                         dest = &local;
927                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
928                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, &ptr);
929                 return TRUE;
930         }
931         return FALSE;
932 }
933
934 MonoArray *
935 mono_metadata_parse_array (MonoMetadata *m, const char *ptr, const char **rptr)
936 {
937         int i;
938         MonoArray *array = g_new0 (MonoArray, 1);
939         
940         array->type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
941         array->rank = mono_metadata_decode_value (ptr, &ptr);
942
943         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
944         if (array->numsizes)
945                 array->sizes = g_new0 (int, array->numsizes);
946         for (i = 0; i < array->numsizes; ++i)
947                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
948
949         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
950         if (array->numlobounds)
951                 array->lobounds = g_new0 (int, array->numlobounds);
952         for (i = 0; i < array->numlobounds; ++i)
953                 array->lobounds [i] = mono_metadata_decode_value (ptr, &ptr);
954
955         if (rptr)
956                 *rptr = ptr;
957         return array;
958 }
959
960 void
961 mono_metadata_free_array (MonoArray *array)
962 {
963         mono_metadata_free_type (array->type);
964         g_free (array->sizes);
965         g_free (array->lobounds);
966         g_free (array);
967 }
968
969 /*
970  * need to add common field and param attributes combinations:
971  * [out] param
972  * public static
973  * public static literal
974  * private
975  * private static
976  * private static literal
977  */
978 static MonoType
979 builtin_types[] = {
980         /* data, attrs, type,              nmods, byref, pinned */
981         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
982         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
983         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
984         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
985         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
986         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
987         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
988         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
989         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
990         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
991         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
992         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
993         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
994         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
995         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
996         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
997         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
998         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
999         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1000         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1001         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1002         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1003         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1004         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1005         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1006         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1007         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1008         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1009         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1010         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1011         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1012         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1013         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1014         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0}
1015 };
1016
1017 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1018
1019 static GHashTable *type_cache = NULL;
1020
1021 /*
1022  * MonoTypes with modifies are never cached, so we never check or use that field.
1023  */
1024 static int
1025 mono_type_hash (MonoType *type)
1026 {
1027         return type->type | (type->byref << 8) | (type->attrs << 9);
1028 }
1029
1030 static gboolean
1031 mono_type_equal (MonoType *a, MonoType *b)
1032 {
1033         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1034                 return 0;
1035         /* need other checks */
1036         return 1;
1037 }
1038
1039 MonoType*
1040 mono_metadata_parse_type (MonoMetadata *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr)
1041 {
1042         MonoType *type, *cached;
1043
1044         if (!type_cache) {
1045                 int i;
1046                 type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1047                 for (i=0; i < NBUILTIN_TYPES (); ++i)
1048                         g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
1049         }
1050
1051         switch (mode) {
1052         case MONO_PARSE_MOD_TYPE:
1053         case MONO_PARSE_PARAM:
1054         case MONO_PARSE_RET:
1055         case MONO_PARSE_FIELD: {
1056                 /* count the modifiers */
1057                 const char *tmp_ptr = ptr;
1058                 int count = 0;
1059                 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1060                         count++;
1061                 if (count) {
1062                         type = g_malloc0 (sizeof (MonoType) + (count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
1063                         type->num_mods = count;
1064                         if (count > 64)
1065                                 g_warning ("got more than 64 modifiers in type");
1066                         /* save them this time */
1067                         count = 0;
1068                         while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr))
1069                                 count++;
1070                         break;
1071                 } /* fall through */
1072         }
1073         case MONO_PARSE_LOCAL:
1074         case MONO_PARSE_TYPE:
1075                 /*
1076                  * Later we can avoid doing this allocation.
1077                  */
1078                 type = g_new0 (MonoType, 1);
1079                 break;
1080         default:
1081                 g_assert_not_reached ();
1082         }
1083         
1084         type->attrs = opt_attrs;
1085         if (mode == MONO_PARSE_LOCAL) {
1086                 /*
1087                  * check for pinned flag
1088                  */
1089                 if (*ptr == MONO_TYPE_PINNED) {
1090                         type->pinned = 1;
1091                         ++ptr;
1092                 }
1093         }
1094
1095         switch (*ptr) {
1096         case MONO_TYPE_BYREF: 
1097                 if (mode == MONO_PARSE_FIELD)
1098                         g_warning ("A field type cannot be byref");
1099                 type->byref = 1; 
1100                 ptr++;
1101                 /* follow through */
1102         default:
1103                 /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET)
1104                         g_error ("void not allowed in param");*/
1105                 do_mono_metadata_parse_type (type, m, ptr, &ptr);
1106                 break;
1107         }
1108         if (rptr)
1109                 *rptr = ptr;
1110         if (mode != MONO_PARSE_PARAM && !type->num_mods && (cached = g_hash_table_lookup (type_cache, type))) {
1111                 mono_metadata_free_type (type);
1112                 return cached;
1113         } else {
1114                 return type;
1115         }
1116 }
1117
1118 MonoMethodSignature *
1119 mono_metadata_parse_method_signature (MonoMetadata *m, int def, const char *ptr, const char **rptr)
1120 {
1121         MonoMethodSignature *method;
1122         int i, align, offset = 0;
1123         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1124
1125         if (*ptr & 0x20)
1126                 hasthis = 1;
1127         if (*ptr & 0x40)
1128                 explicit_this = 1;
1129         call_convention = *ptr & 0x0F;
1130         ptr++;
1131         param_count = mono_metadata_decode_value (ptr, &ptr);
1132
1133         method = g_malloc0 (sizeof (MonoMethodSignature) + (param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1134         method->param_count = param_count;
1135         method->hasthis = hasthis;
1136         method->explicit_this = explicit_this;
1137         method->call_convention = call_convention;
1138         method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, 0, ptr, &ptr);
1139
1140         if (method->hasthis)
1141                 offset += sizeof(gpointer);
1142         if (method->param_count) {
1143                 int size;
1144                 
1145                 method->sentinelpos = -1;
1146                 
1147                 for (i = 0; i < method->param_count; ++i) {
1148                         if (*ptr == MONO_TYPE_SENTINEL) {
1149                                 if (method->call_convention != MONO_CALL_VARARG || def)
1150                                                 g_error ("found sentinel for methoddef or no vararg method");
1151                                 method->sentinelpos = i;
1152                                 ptr++;
1153                         }
1154                         method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, &ptr);
1155                         size = mono_type_size (method->params [i], &align);
1156                         offset += align - 1;
1157                         offset &= ~(align - 1);
1158                         offset += size;
1159                 }
1160         }
1161         method->params_size = offset;
1162
1163         if (rptr)
1164                 *rptr = ptr;
1165         /*
1166          * Add signature to a cache and increase ref count...
1167          */
1168         return method;
1169 }
1170
1171 void
1172 mono_metadata_free_method_signature (MonoMethodSignature *method)
1173 {
1174         int i;
1175         mono_metadata_free_type (method->ret);
1176         for (i = 0; i < method->param_count; ++i)
1177                 mono_metadata_free_type (method->params [i]);
1178
1179         g_free (method);
1180 }
1181
1182 /* 
1183  * do_mono_metadata_parse_type:
1184  * @type: MonoType to be filled in with the return value
1185  * @
1186  * Internal routine used to "fill" the contents of @type from an 
1187  * allocated pointer.  This is done this way to avoid doing too
1188  * many mini-allocations (particularly for the MonoFieldType which
1189  * most of the time is just a MonoType, but sometimes might be augmented).
1190  *
1191  * This routine is used by mono_metadata_parse_type and
1192  * mono_metadata_parse_field_type
1193  *
1194  * This extracts a Type as specified in Partition II (22.2.12) 
1195  */
1196 static void
1197 do_mono_metadata_parse_type (MonoType *type, MonoMetadata *m, const char *ptr, const char **rptr)
1198 {
1199         type->type = mono_metadata_decode_value (ptr, &ptr);
1200         
1201         switch (type->type){
1202         case MONO_TYPE_VOID:
1203         case MONO_TYPE_BOOLEAN:
1204         case MONO_TYPE_CHAR:
1205         case MONO_TYPE_I1:
1206         case MONO_TYPE_U1:
1207         case MONO_TYPE_I2:
1208         case MONO_TYPE_U2:
1209         case MONO_TYPE_I4:
1210         case MONO_TYPE_U4:
1211         case MONO_TYPE_I8:
1212         case MONO_TYPE_U8:
1213         case MONO_TYPE_R4:
1214         case MONO_TYPE_R8:
1215         case MONO_TYPE_I:
1216         case MONO_TYPE_U:
1217         case MONO_TYPE_STRING:
1218         case MONO_TYPE_OBJECT:
1219         case MONO_TYPE_TYPEDBYREF:
1220                 break;
1221         case MONO_TYPE_VALUETYPE:
1222         case MONO_TYPE_CLASS: {
1223                 guint32 token;
1224                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1225                 type->data.klass = mono_class_get (m, token);
1226                 break;
1227         }
1228         case MONO_TYPE_SZARRAY:
1229         case MONO_TYPE_PTR:
1230                 type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
1231                 break;
1232         case MONO_TYPE_FNPTR:
1233                 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1234                 break;
1235         case MONO_TYPE_ARRAY:
1236                 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1237                 break;
1238         default:
1239                 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1240         }
1241         
1242         if (rptr)
1243                 *rptr = ptr;
1244 }
1245
1246 #if 0
1247 /**
1248  * mono_metadata_parse_type:
1249  * @m: metadata context to scan
1250  * @ptr: pointer to encoded Type stream.
1251  * @rptr: the new position in the stream after parsing the type
1252  *
1253  * Returns: A MonoType structure that has the parsed information
1254  * from the type stored at @ptr in the metadata table @m.
1255  */
1256 MonoType *
1257 mono_metadata_parse_type (MonoMetadata *m, const char *ptr, const char **rptr)
1258 {
1259         /* should probably be allocated in a memchunk */
1260         MonoType *type = g_new0(MonoType, 1);
1261
1262         do_mono_metadata_parse_type (type, m, ptr, rptr);
1263
1264         return type;
1265 }
1266 #endif
1267
1268 void
1269 mono_metadata_free_type (MonoType *type)
1270 {
1271         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
1272                 return;
1273         switch (type->type){
1274         case MONO_TYPE_SZARRAY:
1275         case MONO_TYPE_PTR:
1276                 mono_metadata_free_type (type->data.type);
1277                 break;
1278         case MONO_TYPE_FNPTR:
1279                 mono_metadata_free_method_signature (type->data.method);
1280                 break;
1281         case MONO_TYPE_ARRAY:
1282                 mono_metadata_free_array (type->data.array);
1283                 break;
1284         }
1285         g_free (type);
1286 }
1287
1288 static void
1289 hex_dump (const char *buffer, int base, int count)
1290 {
1291         int show_header = 1;
1292         int i;
1293
1294         if (count < 0){
1295                 count = -count;
1296                 show_header = 0;
1297         }
1298         
1299         for (i = 0; i < count; i++){
1300                 if (show_header)
1301                         if ((i % 16) == 0)
1302                                 printf ("\n0x%08x: ", (unsigned char) base + i);
1303
1304                 printf ("%02x ", (unsigned char) (buffer [i]));
1305         }
1306         fflush (stdout);
1307 }
1308
1309 /** 
1310  * @mh: The Method header
1311  * @ptr: Points to the beginning of the Section Data (25.3)
1312  */
1313 static void
1314 parse_section_data (MonoMethodHeader *mh, const unsigned char *ptr)
1315 {
1316         unsigned char sect_data_flags;
1317         const unsigned char *sptr;
1318         int is_fat;
1319         guint32 sect_data_len;
1320         
1321         while (1) {
1322                 /* align on 32-bit boundary */
1323                 /* FIXME: not 64-bit clean code */
1324                 sptr = ptr = dword_align (ptr); 
1325                 sect_data_flags = *ptr;
1326                 ptr++;
1327                 
1328                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1329                 if (is_fat) {
1330                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
1331                         ptr += 3;
1332                 } else {
1333                         sect_data_len = ptr [0];
1334                         ++ptr;
1335                 }
1336                 /*
1337                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
1338                 hex_dump (sptr, 0, sect_data_len+8);
1339                 g_print ("\nheader: ");
1340                 hex_dump (sptr-4, 0, 4);
1341                 g_print ("\n");
1342                 */
1343                 
1344                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1345                         const unsigned char *p = dword_align (ptr);
1346                         int i;
1347                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
1348                         /* we could just store a pointer if we don't need to byteswap */
1349                         mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
1350                         for (i = 0; i < mh->num_clauses; ++i) {
1351                                 MonoExceptionClause *ec = &mh->clauses [i];
1352                                 if (is_fat) {
1353                                         /* we could memcpy and byteswap */
1354                                         ec->flags = read32 (p);
1355                                         p += 4;
1356                                         ec->try_offset = read32 (p);
1357                                         p += 4;
1358                                         ec->try_len = read32 (p);
1359                                         p += 4;
1360                                         ec->handler_offset = read32 (p);
1361                                         p += 4;
1362                                         ec->handler_len = read32 (p);
1363                                         p += 4;
1364                                         ec->token_or_filter = read32 (p);
1365                                         p += 4;
1366                                 } else {
1367                                         ec->flags = read16 (p);
1368                                         p += 2;
1369                                         ec->try_offset = read16 (p);
1370                                         p += 2;
1371                                         ec->try_len = *p;
1372                                         ++p;
1373                                         ec->handler_offset = read16 (p);
1374                                         p += 2;
1375                                         ec->handler_len = *p;
1376                                         ++p;
1377                                         ec->token_or_filter = read32 (p);
1378                                         p += 4;
1379                                 }
1380                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
1381                         }
1382                 }
1383                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
1384                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
1385                 else
1386                         return;
1387         }
1388 }
1389
1390 MonoMethodHeader *
1391 mono_metadata_parse_mh (MonoMetadata *m, const char *ptr)
1392 {
1393         MonoMethodHeader *mh;
1394         unsigned char flags = *(unsigned char *) ptr;
1395         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1396         guint16 fat_flags;
1397         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
1398         const unsigned char *code;
1399         int hsize;
1400         
1401         g_return_val_if_fail (ptr != NULL, NULL);
1402
1403         switch (format){
1404         case METHOD_HEADER_TINY_FORMAT:
1405                 mh = g_new0 (MonoMethodHeader, 1);
1406                 ptr++;
1407                 mh->max_stack = 8;
1408                 local_var_sig_tok = 0;
1409                 mh->code_size = flags >> 2;
1410                 mh->code = ptr;
1411                 return mh;
1412         case METHOD_HEADER_TINY_FORMAT1:
1413                 mh = g_new0 (MonoMethodHeader, 1);
1414                 ptr++;
1415                 mh->max_stack = 8;
1416                 local_var_sig_tok = 0;
1417
1418                 /*
1419                  * The spec claims 3 bits, but the Beta2 is
1420                  * incorrect
1421                  */
1422                 mh->code_size = flags >> 2;
1423                 mh->code = ptr;
1424                 return mh;
1425         case METHOD_HEADER_FAT_FORMAT:
1426                 fat_flags = read16 (ptr);
1427                 ptr += 2;
1428                 hsize = (fat_flags >> 12) & 0xf;
1429                 max_stack = read16 (ptr);
1430                 ptr += 2;
1431                 code_size = read32 (ptr);
1432                 ptr += 4;
1433                 local_var_sig_tok = read32 (ptr);
1434                 ptr += 4;
1435
1436                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1437                         init_locals = 1;
1438                 else
1439                         init_locals = 0;
1440
1441                 code = ptr;
1442
1443                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1444                         break;
1445
1446                 /*
1447                  * There are more sections
1448                  */
1449                 ptr = code + code_size;
1450                 
1451                 break;
1452                 
1453         default:
1454                 return NULL;
1455         }
1456                        
1457         if (local_var_sig_tok) {
1458                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
1459                 const char *ptr;
1460                 guint32 cols [MONO_STAND_ALONG_SIGNATURE_SIZE];
1461                 int len=0, i, bsize;
1462                 guint offset = 0;
1463
1464                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
1465                 ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONG_SIGNATURE]);
1466                 bsize = mono_metadata_decode_blob_size (ptr, &ptr);
1467                 if (*ptr != 0x07)
1468                         g_warning ("wrong signature for locals blob");
1469                 ptr++;
1470                 len = mono_metadata_decode_value (ptr, &ptr);
1471                 mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1472                 mh->num_locals = len;
1473                 for (i = 0; i < len; ++i) {
1474                         int val;
1475                         int align;
1476                         mh->locals [i] = mono_metadata_parse_type (m, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1477
1478                         val = mono_type_size (mh->locals [i], &align);
1479                         offset += align - 1;
1480                         offset &= ~(align - 1);
1481                         offset += val;
1482                 }
1483                 mh->locals_size = offset;
1484         } else {
1485                 mh = g_new0 (MonoMethodHeader, 1);
1486         }
1487         mh->code = code;
1488         mh->code_size = code_size;
1489         mh->max_stack = max_stack;
1490         mh->init_locals = init_locals;
1491         if (fat_flags & METHOD_HEADER_MORE_SECTS)
1492                 parse_section_data (mh, (const unsigned char*)ptr);
1493         return mh;
1494 }
1495
1496 void
1497 mono_metadata_free_mh (MonoMethodHeader *mh)
1498 {
1499         int i;
1500         for (i = 0; i < mh->num_locals; ++i)
1501                 mono_metadata_free_type (mh->locals[i]);
1502         g_free (mh->clauses);
1503         g_free (mh);
1504 }
1505
1506 /**
1507  * mono_metadata_parse_field_type:
1508  * @m: metadata context to extract information from
1509  * @ptr: pointer to the field signature
1510  *
1511  * Parses the field signature, and returns the type information for it. 
1512  *
1513  * Returns: The MonoType that was extracted from @ptr.
1514  */
1515 MonoType *
1516 mono_metadata_parse_field_type (MonoMetadata *m, short field_flags, const char *ptr, const char **rptr)
1517 {
1518         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
1519 }
1520
1521 MonoType *
1522 mono_metadata_parse_param (MonoMetadata *m, const char *ptr, const char **rptr)
1523 {
1524         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
1525 }
1526
1527 /*
1528  * mono_metadata_token_from_dor:
1529  * @dor_token: A TypeDefOrRef coded index
1530  *
1531  * dor_token is a TypeDefOrRef coded index: it contains either
1532  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
1533  * bits contain an index into the table.
1534  *
1535  * Returns: an expanded token
1536  */
1537 guint32
1538 mono_metadata_token_from_dor (guint32 dor_index)
1539 {
1540         guint32 table, idx;
1541
1542         table = dor_index & 0x03;
1543         idx = dor_index >> 2;
1544
1545         switch (table){
1546         case 0: /* TypeDef */
1547                 return MONO_TOKEN_TYPE_DEF | idx;
1548
1549         case 1: /* TypeRef */
1550                 return MONO_TOKEN_TYPE_REF | idx;
1551
1552         case 2: /* TypeSpec */
1553                 return MONO_TOKEN_TYPE_SPEC | idx;
1554
1555         default:
1556                 g_assert_not_reached ();
1557         }
1558
1559         return 0;
1560 }
1561
1562 /*
1563  * We use this to pass context information to the row locator
1564  */
1565 typedef struct {
1566         int idx;                        /* The index that we are trying to locate */
1567         int col_idx;            /* The index in the row where idx may be stored */
1568         MonoTableInfo *t;       /* pointer to the table */
1569         guint32 result;
1570 } locator_t;
1571
1572 #define CSIZE(x) (sizeof (x) / 4)
1573
1574 /*
1575  * How the row locator works.
1576  *
1577  *   Table A
1578  *   ___|___
1579  *   ___|___         Table B
1580  *   ___|___------>  _______
1581  *   ___|___         _______
1582  *   
1583  * A column in the rows of table A references an index in table B.
1584  * For example A may be the TYPEDEF table and B the METHODDEF table.
1585  * 
1586  * Given an index in table B we want to get the row in table A
1587  * where the column n references our index in B.
1588  *
1589  * In the locator_t structure:
1590  *      t is table A
1591  *      col_idx is the column number
1592  *      index is the index in table B
1593  *      result will be the index in table A
1594  *
1595  * Examples:
1596  * Table A              Table B         column (in table A)
1597  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
1598  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
1599  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
1600  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
1601  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
1602  *
1603  * Note that we still don't support encoded indexes.
1604  *
1605  */
1606 static int
1607 typedef_locator (const void *a, const void *b)
1608 {
1609         locator_t *loc = (locator_t *) a;
1610         char *bb = (char *) b;
1611         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
1612         guint32 col, col_next;
1613
1614         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
1615
1616         if (loc->idx < col)
1617                 return -1;
1618
1619         /*
1620          * Need to check that the next row is valid.
1621          */
1622         if (typedef_index + 1 < loc->t->rows) {
1623                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
1624                 if (loc->idx >= col_next)
1625                         return 1;
1626
1627                 if (col == col_next)
1628                         return 1; 
1629         }
1630
1631         loc->result = typedef_index;
1632         
1633         return 0;
1634 }
1635
1636 static int
1637 table_locator (const void *a, const void *b)
1638 {
1639         locator_t *loc = (locator_t *) a;
1640         char *bb = (char *) b;
1641         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
1642         guint32 col;
1643         
1644         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
1645
1646         if (loc->idx == col) {
1647                 loc->result = table_index;
1648                 return 0;
1649         }
1650         if (loc->idx < col)
1651                 return -1;
1652         else 
1653                 return 1;
1654 }
1655
1656 guint32
1657 mono_metadata_typedef_from_field (MonoMetadata *meta, guint32 index)
1658 {
1659         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1660         locator_t loc;
1661         
1662         loc.idx = mono_metadata_token_index (index);
1663         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
1664         loc.t = tdef;
1665
1666         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1667                 g_assert_not_reached ();
1668
1669         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1670         return loc.result + 1;
1671 }
1672
1673 guint32
1674 mono_metadata_typedef_from_method (MonoMetadata *meta, guint32 index)
1675 {
1676         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1677         locator_t loc;
1678         
1679         loc.idx = mono_metadata_token_index (index);
1680         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
1681         loc.t = tdef;
1682
1683         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1684                 g_assert_not_reached ();
1685
1686         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1687         return loc.result + 1;
1688 }
1689
1690 MonoClass**
1691 mono_metadata_interfaces_from_typedef (MonoMetadata *meta, guint32 index)
1692 {
1693         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
1694         locator_t loc;
1695         guint32 start, i;
1696         guint32 cols [MONO_INTERFACEIMPL_SIZE];
1697         MonoClass **result;
1698         
1699         loc.idx = mono_metadata_token_index (index);
1700         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
1701         loc.t = tdef;
1702
1703         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
1704                 return NULL;
1705
1706         start = loc.result;
1707         /*
1708          * We may end up in the middle of the rows... 
1709          */
1710         while (start > 0) {
1711                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
1712                         start--;
1713                 else
1714                         break;
1715         }
1716         result = NULL;
1717         i = 0;
1718         while (start < tdef->rows) {
1719                 mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE);
1720                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
1721                         break;
1722                 result = g_renew (MonoClass*, result, i + 2);
1723                 result [i] = mono_class_get (meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]));
1724                 ++i;
1725                 ++start;
1726         }
1727         result [i] = NULL;
1728         return result;
1729 }
1730
1731 #ifndef __GNUC__
1732 #define __alignof__(a) sizeof(a)
1733 #endif
1734
1735 /*
1736  * mono_type_size:
1737  * @t: the type to return the size of
1738  *
1739  * Returns: the number of bytes required to hold an instance of this
1740  * type in memory
1741  */
1742 int
1743 mono_type_size (MonoType *t, gint *align)
1744 {
1745         if (!t) {
1746                 *align = 1;
1747                 return 0;
1748         }
1749         if (t->byref) {
1750                 *align = __alignof__(gpointer);
1751                 return sizeof (gpointer);
1752         }
1753
1754         switch (t->type){
1755         case MONO_TYPE_VOID:
1756                 *align = 1;
1757                 return 0;
1758         case MONO_TYPE_BOOLEAN:
1759                 *align = __alignof__(char);
1760                 return sizeof (char);
1761                 
1762         case MONO_TYPE_CHAR:
1763                 *align = __alignof__(short);
1764                 return sizeof (short);
1765                 
1766         case MONO_TYPE_I1:
1767         case MONO_TYPE_U1:
1768                 *align = __alignof__(char);
1769                 return 1;
1770                 
1771         case MONO_TYPE_I2:
1772         case MONO_TYPE_U2:
1773                 *align = __alignof__(gint16);
1774                 return 2;
1775                 
1776         case MONO_TYPE_I4:
1777         case MONO_TYPE_U4:
1778                 *align = __alignof__(gint32);
1779                 return 4;
1780         case MONO_TYPE_R4:
1781                 *align = __alignof__(float);
1782                 return 4;
1783                 
1784         case MONO_TYPE_I8:
1785         case MONO_TYPE_U8:
1786                 *align = __alignof__(gint64);
1787         case MONO_TYPE_R8:
1788                 *align = __alignof__(double);
1789                 return 8;
1790                 
1791         case MONO_TYPE_I:
1792         case MONO_TYPE_U:
1793                 *align = __alignof__(gpointer);
1794                 return sizeof (gpointer);
1795                 
1796         case MONO_TYPE_STRING:
1797                 *align = __alignof__(gpointer);
1798                 return sizeof (gpointer);
1799                 
1800         case MONO_TYPE_OBJECT:
1801                 *align = __alignof__(gpointer);
1802                 return sizeof (gpointer);
1803                 
1804         case MONO_TYPE_VALUETYPE: {
1805                 guint32 size;
1806
1807                 size = mono_class_value_size (t->data.klass, align);
1808                 return size;
1809         }
1810         case MONO_TYPE_CLASS:
1811         case MONO_TYPE_SZARRAY:
1812         case MONO_TYPE_PTR:
1813         case MONO_TYPE_FNPTR:
1814         case MONO_TYPE_ARRAY:
1815         case MONO_TYPE_TYPEDBYREF: /* we may want to use a struct {MonoType* type, void *data } instead ...*/
1816                 *align = __alignof__(gpointer);
1817                 return sizeof (gpointer);
1818         default:
1819                 g_error ("type 0x%02x unknown", t->type);
1820         }
1821         return 0;
1822 }
1823
1824 gboolean
1825 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
1826 {
1827         if (t1->type != t2->type ||
1828             t1->byref != t2->byref)
1829                 return FALSE;
1830
1831         switch (t1->type) {
1832         case MONO_TYPE_VOID:
1833         case MONO_TYPE_BOOLEAN:
1834         case MONO_TYPE_CHAR:
1835         case MONO_TYPE_I1:
1836         case MONO_TYPE_U1:
1837         case MONO_TYPE_I2:
1838         case MONO_TYPE_U2:
1839         case MONO_TYPE_I4:
1840         case MONO_TYPE_U4:
1841         case MONO_TYPE_I8:
1842         case MONO_TYPE_U8:
1843         case MONO_TYPE_R4:
1844         case MONO_TYPE_R8:
1845         case MONO_TYPE_STRING:
1846         case MONO_TYPE_I:
1847         case MONO_TYPE_U:
1848         case MONO_TYPE_OBJECT:
1849                 break;
1850         case MONO_TYPE_VALUETYPE:
1851         case MONO_TYPE_CLASS:
1852         case MONO_TYPE_SZARRAY:
1853                 return t1->data.klass == t2->data.klass;
1854         default:
1855                 g_error ("implement type compare for %0x!", t1->type);
1856                 return FALSE;
1857         }
1858
1859         return TRUE;
1860 }
1861
1862 gboolean
1863 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
1864 {
1865         int i;
1866
1867         if (sig1->hasthis != sig2->hasthis ||
1868             sig1->param_count != sig2->param_count)
1869                 return FALSE;
1870
1871         for (i = 0; i < sig1->param_count; i++) { 
1872                 MonoType *p1 = sig1->params[i];
1873                 MonoType *p2 = sig2->params[i];
1874                 
1875                 if (p1->attrs != p2->attrs)
1876                         return FALSE;
1877                 
1878                 if (!mono_metadata_type_equal (p1, p2))
1879                         return FALSE;
1880         }
1881
1882         return TRUE;
1883 }
1884