Mon Nov 19 11:37:14 CET 2001 Paolo Molaro <lupus@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 "mono-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 int
370 mono_metadata_compute_size (MonoMetadata *meta, 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         MonoMetaTable *table = tables [tableindex].table;
377
378         for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
379                 switch (code){
380                 case MONO_MT_UINT32:
381                         field_size = 4; break;
382                         
383                 case MONO_MT_UINT16:
384                         field_size = 2; break;
385                         
386                 case MONO_MT_UINT8:
387                         field_size = 1; break;
388                         
389                 case MONO_MT_BLOB_IDX:
390                         field_size = meta->idx_blob_wide ? 4 : 2; break;
391                         
392                 case MONO_MT_STRING_IDX:
393                         field_size = meta->idx_string_wide ? 4 : 2; break;
394                         
395                 case MONO_MT_GUID_IDX:
396                         field_size = meta->idx_guid_wide ? 4 : 2; break;
397
398                 case MONO_MT_TABLE_IDX:
399                         /* Uhm, a table index can point to other tables besides the current one
400                          * so, it's not correct to use the rowcount of the current table to
401                          * get the size for this column - lupus 
402                          */
403                         switch (tableindex) {
404                         case MONO_TABLE_ASSEMBLYREFOS:
405                                 g_assert (i == 3);
406                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
407                         case MONO_TABLE_ASSEMBLYPROCESSOR:
408                                 g_assert (i == 1);
409                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
410                         case MONO_TABLE_CLASSLAYOUT:
411                                 g_assert (i == 2);
412                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
413                         case MONO_TABLE_EVENTMAP:
414                                 g_assert (i == 0 || i == 1);
415                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
416                                         idx_size(MONO_TABLE_TYPEDEF); 
417                                 break;
418                         case MONO_TABLE_EVENT:
419                                 g_assert (i == 2);
420                                 field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
421                                 field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
422                                 break;
423                         case MONO_TABLE_EXPORTEDTYPE:
424                                 g_assert (i == 1);
425                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
426                         case MONO_TABLE_FIELDLAYOUT:
427                                 g_assert (i == 1);
428                                 field_size = idx_size (MONO_TABLE_FIELD); break;
429                         case MONO_TABLE_FIELDRVA:
430                                 g_assert (i == 1);
431                                 field_size = idx_size (MONO_TABLE_FIELD); break;
432                         case MONO_TABLE_IMPLMAP:
433                                 g_assert (i == 3);
434                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
435                         case MONO_TABLE_INTERFACEIMPL:
436                                 g_assert (i == 0);
437                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
438                         case MONO_TABLE_METHOD:
439                                 g_assert (i == 5);
440                                 field_size = idx_size (MONO_TABLE_PARAM); break;
441                         case MONO_TABLE_METHODIMPL:
442                                 g_assert (i == 0);
443                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
444                         case MONO_TABLE_METHODSEMANTICS:
445                                 g_assert (i == 1);
446                                 field_size = idx_size (MONO_TABLE_METHOD); break;
447                         case MONO_TABLE_NESTEDCLASS:
448                                 g_assert (i == 0 || i == 1);
449                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
450                         case MONO_TABLE_PROPERTYMAP:
451                                 g_assert (i == 0 || i == 1);
452                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
453                                         idx_size(MONO_TABLE_TYPEDEF); 
454                                 break;
455                         case MONO_TABLE_TYPEDEF:
456                                 g_assert (i == 4 || i == 5);
457                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
458                                         idx_size(MONO_TABLE_METHOD); 
459                                 break;
460                         default:
461                                 g_assert_not_reached ();
462                         }
463                         if (field_size != idx_size (tableindex))
464                                 g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
465                         
466                         break;
467
468                         /*
469                          * HasConstant: ParamDef, FieldDef, Property
470                          */
471                 case MONO_MT_CONST_IDX:
472                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
473                                  meta->tables [MONO_TABLE_FIELD].rows);
474                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
475
476                         /* 2 bits to encode tag */
477                         field_size = rtsize (n, 16-2);
478                         break;
479
480                         /*
481                          * HasCustomAttribute: points to any table but
482                          * itself.
483                          */
484                 case MONO_MT_HASCAT_IDX:
485                         /*
486                          * We believe that since the signature and
487                          * permission are indexing the Blob heap,
488                          * we should consider the blob size first
489                          */
490                         /* I'm not a believer - lupus
491                         if (meta->idx_blob_wide){
492                                 field_size = 4;
493                                 break;
494                         }*/
495                         
496                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
497                                  meta->tables [MONO_TABLE_FIELD].rows);
498                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
499                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
500                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
501                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
502                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
503                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
504                         /* Permission seems to be a blob heap pointer */
505                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
506                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
507                         /* Signature seems to be a blob heap pointer */
508                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
509                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
510                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
511                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
512                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
513                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
514                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
515
516                         /* 5 bits to encode */
517                         field_size = rtsize (n, 16-5);
518                         break;
519
520                         /*
521                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
522                          * MemberRef and String.  
523                          */
524                 case MONO_MT_CAT_IDX:
525                         /* String is a heap, if it is wide, we know the size */
526                         /* See above, nope. 
527                         if (meta->idx_string_wide){
528                                 field_size = 4;
529                                 break;
530                         }*/
531                         
532                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
533                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
534                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
535                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
536
537                         /* 3 bits to encode */
538                         field_size = rtsize (n, 16-3);
539                         break;
540
541                         /*
542                          * HasDeclSecurity: Typedef, MethodDef, Assembly
543                          */
544                 case MONO_MT_HASDEC_IDX:
545                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
546                                  meta->tables [MONO_TABLE_METHOD].rows);
547                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
548
549                         /* 2 bits to encode */
550                         field_size = rtsize (n, 16-2);
551                         break;
552
553                         /*
554                          * Implementation: File, AssemblyRef, ExportedType
555                          */
556                 case MONO_MT_IMPL_IDX:
557                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
558                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
559                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
560
561                         /* 2 bits to encode tag */
562                         field_size = rtsize (n, 16-2);
563                         break;
564
565                         /*
566                          * HasFieldMarshall: FieldDef, ParamDef
567                          */
568                 case MONO_MT_HFM_IDX:
569                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
570                                  meta->tables [MONO_TABLE_PARAM].rows);
571
572                         /* 1 bit used to encode tag */
573                         field_size = rtsize (n, 16-1);
574                         break;
575
576                         /*
577                          * MemberForwarded: FieldDef, MethodDef
578                          */
579                 case MONO_MT_MF_IDX:
580                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
581                                  meta->tables [MONO_TABLE_METHOD].rows);
582
583                         /* 1 bit used to encode tag */
584                         field_size = rtsize (n, 16-1);
585                         break;
586
587                         /*
588                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
589                          * LAMESPEC
590                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
591                          */
592                 case MONO_MT_TDOR_IDX:
593                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
594                                  meta->tables [MONO_TABLE_TYPEREF].rows);
595                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
596
597                         /* 2 bits to encode */
598                         field_size = rtsize (n, 16-2);
599                         break;
600
601                         /*
602                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
603                          */
604                 case MONO_MT_MRP_IDX:
605                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
606                                  meta->tables [MONO_TABLE_TYPEREF].rows);
607                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
608                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
609                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
610                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
611
612                         /* 3 bits to encode */
613                         field_size = rtsize (n, 16 - 3);
614                         break;
615                         
616                 case MONO_MT_MDOR_IDX:
617
618                         /*
619                          * MethodDefOrRef: MethodDef, MemberRef
620                          */
621                 case MONO_MT_HS_IDX:
622                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
623                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
624
625                         /* 1 bit used to encode tag */
626                         field_size = rtsize (n, 16-1);
627                         break;
628
629                         /*
630                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
631                          */
632                 case MONO_MT_RS_IDX:
633                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
634                                  meta->tables [MONO_TABLE_MODULEREF].rows);
635                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
636                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
637
638                         /* 2 bits used to encode tag (ECMA spec claims 3) */
639                         field_size = rtsize (n, 16 - 2);
640                         break;
641                 }
642
643                 /*
644                  * encode field size as follows (we just need to
645                  * distinguish them).
646                  *
647                  * 4 -> 3
648                  * 2 -> 1
649                  * 1 -> 0
650                  */
651                 bitfield |= (field_size-1) << shift;
652                 shift += 2;
653                 size += field_size;
654                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
655         }
656
657         *result_bitfield = (i << 24) | bitfield;
658         return size;
659 }
660
661 /**
662  * mono_metadata_compute_table_bases:
663  * @meta: metadata context to compute table values
664  *
665  * Computes the table bases for the metadata structure.
666  * This is an internal function used by the image loader code.
667  */
668 void
669 mono_metadata_compute_table_bases (MonoMetadata *meta)
670 {
671         int i;
672         char *base = meta->tables_base;
673         
674         for (i = 0; i < 64; i++){
675                 if (meta->tables [i].rows == 0)
676                         continue;
677
678                 meta->tables [i].row_size = mono_metadata_compute_size (
679                         meta, i, &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 MonoArrayType *
935 mono_metadata_parse_array (MonoMetadata *m, const char *ptr, const char **rptr)
936 {
937         int i;
938         MonoArrayType *array = g_new0 (MonoArrayType, 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 (MonoArrayType *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 guint
1025 mono_type_hash (gconstpointer data)
1026 {
1027         MonoType *type = (MonoType *) data;
1028         return type->type | (type->byref << 8) | (type->attrs << 9);
1029 }
1030
1031 static gint
1032 mono_type_equal (gconstpointer ka, gconstpointer kb)
1033 {
1034         MonoType *a = (MonoType *) ka;
1035         MonoType *b = (MonoType *) kb;
1036         
1037         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1038                 return 0;
1039         /* need other checks */
1040         return 1;
1041 }
1042
1043 MonoType*
1044 mono_metadata_parse_type (MonoMetadata *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr)
1045 {
1046         MonoType *type, *cached;
1047
1048         if (!type_cache) {
1049                 int i;
1050                 type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1051
1052                 for (i = 0; i < NBUILTIN_TYPES (); ++i)
1053                         g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
1054         }
1055
1056         switch (mode) {
1057         case MONO_PARSE_MOD_TYPE:
1058         case MONO_PARSE_PARAM:
1059         case MONO_PARSE_RET:
1060         case MONO_PARSE_FIELD: {
1061                 /* count the modifiers */
1062                 const char *tmp_ptr = ptr;
1063                 int count = 0;
1064                 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1065                         count++;
1066                 if (count) {
1067                         type = g_malloc0 (sizeof (MonoType) + (count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
1068                         type->num_mods = count;
1069                         if (count > 64)
1070                                 g_warning ("got more than 64 modifiers in type");
1071                         /* save them this time */
1072                         count = 0;
1073                         while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr))
1074                                 count++;
1075                         break;
1076                 } /* fall through */
1077         }
1078         case MONO_PARSE_LOCAL:
1079         case MONO_PARSE_TYPE:
1080                 /*
1081                  * Later we can avoid doing this allocation.
1082                  */
1083                 type = g_new0 (MonoType, 1);
1084                 break;
1085         default:
1086                 g_assert_not_reached ();
1087         }
1088         
1089         type->attrs = opt_attrs;
1090         if (mode == MONO_PARSE_LOCAL) {
1091                 /*
1092                  * check for pinned flag
1093                  */
1094                 if (*ptr == MONO_TYPE_PINNED) {
1095                         type->pinned = 1;
1096                         ++ptr;
1097                 }
1098         }
1099
1100         switch (*ptr) {
1101         case MONO_TYPE_BYREF: 
1102                 if (mode == MONO_PARSE_FIELD)
1103                         g_warning ("A field type cannot be byref");
1104                 type->byref = 1; 
1105                 ptr++;
1106                 /* follow through */
1107         default:
1108                 /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET)
1109                         g_error ("void not allowed in param");*/
1110                 do_mono_metadata_parse_type (type, m, ptr, &ptr);
1111                 break;
1112         }
1113         if (rptr)
1114                 *rptr = ptr;
1115         if (mode != MONO_PARSE_PARAM && !type->num_mods && (cached = g_hash_table_lookup (type_cache, type))) {
1116                 mono_metadata_free_type (type);
1117                 return cached;
1118         } else {
1119                 return type;
1120         }
1121 }
1122
1123 MonoMethodSignature *
1124 mono_metadata_parse_method_signature (MonoMetadata *m, int def, const char *ptr, const char **rptr)
1125 {
1126         MonoMethodSignature *method;
1127         int i, align, offset = 0;
1128         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1129
1130         if (*ptr & 0x20)
1131                 hasthis = 1;
1132         if (*ptr & 0x40)
1133                 explicit_this = 1;
1134         call_convention = *ptr & 0x0F;
1135         ptr++;
1136         param_count = mono_metadata_decode_value (ptr, &ptr);
1137
1138         method = g_malloc0 (sizeof (MonoMethodSignature) + (param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1139         method->param_count = param_count;
1140         method->hasthis = hasthis;
1141         method->explicit_this = explicit_this;
1142         method->call_convention = call_convention;
1143         method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, 0, ptr, &ptr);
1144
1145         if (method->hasthis)
1146                 offset += sizeof(gpointer);
1147         if (method->param_count) {
1148                 int size;
1149                 
1150                 method->sentinelpos = -1;
1151                 
1152                 for (i = 0; i < method->param_count; ++i) {
1153                         if (*ptr == MONO_TYPE_SENTINEL) {
1154                                 if (method->call_convention != MONO_CALL_VARARG || def)
1155                                                 g_error ("found sentinel for methoddef or no vararg method");
1156                                 method->sentinelpos = i;
1157                                 ptr++;
1158                         }
1159                         method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, &ptr);
1160                         size = mono_type_size (method->params [i], &align);
1161                         offset += align - 1;
1162                         offset &= ~(align - 1);
1163                         offset += size;
1164                 }
1165         }
1166         method->params_size = offset;
1167
1168         if (rptr)
1169                 *rptr = ptr;
1170         /*
1171          * Add signature to a cache and increase ref count...
1172          */
1173         return method;
1174 }
1175
1176 void
1177 mono_metadata_free_method_signature (MonoMethodSignature *method)
1178 {
1179         int i;
1180         mono_metadata_free_type (method->ret);
1181         for (i = 0; i < method->param_count; ++i)
1182                 mono_metadata_free_type (method->params [i]);
1183
1184         g_free (method);
1185 }
1186
1187 /* 
1188  * do_mono_metadata_parse_type:
1189  * @type: MonoType to be filled in with the return value
1190  * @
1191  * Internal routine used to "fill" the contents of @type from an 
1192  * allocated pointer.  This is done this way to avoid doing too
1193  * many mini-allocations (particularly for the MonoFieldType which
1194  * most of the time is just a MonoType, but sometimes might be augmented).
1195  *
1196  * This routine is used by mono_metadata_parse_type and
1197  * mono_metadata_parse_field_type
1198  *
1199  * This extracts a Type as specified in Partition II (22.2.12) 
1200  */
1201 static void
1202 do_mono_metadata_parse_type (MonoType *type, MonoMetadata *m, const char *ptr, const char **rptr)
1203 {
1204         type->type = mono_metadata_decode_value (ptr, &ptr);
1205         
1206         switch (type->type){
1207         case MONO_TYPE_VOID:
1208         case MONO_TYPE_BOOLEAN:
1209         case MONO_TYPE_CHAR:
1210         case MONO_TYPE_I1:
1211         case MONO_TYPE_U1:
1212         case MONO_TYPE_I2:
1213         case MONO_TYPE_U2:
1214         case MONO_TYPE_I4:
1215         case MONO_TYPE_U4:
1216         case MONO_TYPE_I8:
1217         case MONO_TYPE_U8:
1218         case MONO_TYPE_R4:
1219         case MONO_TYPE_R8:
1220         case MONO_TYPE_I:
1221         case MONO_TYPE_U:
1222         case MONO_TYPE_STRING:
1223         case MONO_TYPE_OBJECT:
1224         case MONO_TYPE_TYPEDBYREF:
1225                 break;
1226         case MONO_TYPE_VALUETYPE:
1227         case MONO_TYPE_CLASS: {
1228                 guint32 token;
1229                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1230                 type->data.klass = mono_class_get (m, token);
1231                 break;
1232         }
1233         case MONO_TYPE_SZARRAY:
1234         case MONO_TYPE_PTR:
1235                 type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
1236                 break;
1237         case MONO_TYPE_FNPTR:
1238                 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1239                 break;
1240         case MONO_TYPE_ARRAY:
1241                 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1242                 break;
1243         default:
1244                 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1245         }
1246         
1247         if (rptr)
1248                 *rptr = ptr;
1249 }
1250
1251 #if 0
1252 /**
1253  * mono_metadata_parse_type:
1254  * @m: metadata context to scan
1255  * @ptr: pointer to encoded Type stream.
1256  * @rptr: the new position in the stream after parsing the type
1257  *
1258  * Returns: A MonoType structure that has the parsed information
1259  * from the type stored at @ptr in the metadata table @m.
1260  */
1261 MonoType *
1262 mono_metadata_parse_type (MonoMetadata *m, const char *ptr, const char **rptr)
1263 {
1264         /* should probably be allocated in a memchunk */
1265         MonoType *type = g_new0(MonoType, 1);
1266
1267         do_mono_metadata_parse_type (type, m, ptr, rptr);
1268
1269         return type;
1270 }
1271 #endif
1272
1273 void
1274 mono_metadata_free_type (MonoType *type)
1275 {
1276         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
1277                 return;
1278         switch (type->type){
1279         case MONO_TYPE_SZARRAY:
1280         case MONO_TYPE_PTR:
1281                 mono_metadata_free_type (type->data.type);
1282                 break;
1283         case MONO_TYPE_FNPTR:
1284                 mono_metadata_free_method_signature (type->data.method);
1285                 break;
1286         case MONO_TYPE_ARRAY:
1287                 mono_metadata_free_array (type->data.array);
1288                 break;
1289         }
1290         g_free (type);
1291 }
1292
1293 static void
1294 hex_dump (const char *buffer, int base, int count)
1295 {
1296         int show_header = 1;
1297         int i;
1298
1299         if (count < 0){
1300                 count = -count;
1301                 show_header = 0;
1302         }
1303         
1304         for (i = 0; i < count; i++){
1305                 if (show_header)
1306                         if ((i % 16) == 0)
1307                                 printf ("\n0x%08x: ", (unsigned char) base + i);
1308
1309                 printf ("%02x ", (unsigned char) (buffer [i]));
1310         }
1311         fflush (stdout);
1312 }
1313
1314 /** 
1315  * @mh: The Method header
1316  * @ptr: Points to the beginning of the Section Data (25.3)
1317  */
1318 static void
1319 parse_section_data (MonoMethodHeader *mh, const unsigned char *ptr)
1320 {
1321         unsigned char sect_data_flags;
1322         const unsigned char *sptr;
1323         int is_fat;
1324         guint32 sect_data_len;
1325         
1326         while (1) {
1327                 /* align on 32-bit boundary */
1328                 /* FIXME: not 64-bit clean code */
1329                 sptr = ptr = dword_align (ptr); 
1330                 sect_data_flags = *ptr;
1331                 ptr++;
1332                 
1333                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1334                 if (is_fat) {
1335                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
1336                         ptr += 3;
1337                 } else {
1338                         sect_data_len = ptr [0];
1339                         ++ptr;
1340                 }
1341                 /*
1342                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
1343                 hex_dump (sptr, 0, sect_data_len+8);
1344                 g_print ("\nheader: ");
1345                 hex_dump (sptr-4, 0, 4);
1346                 g_print ("\n");
1347                 */
1348                 
1349                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1350                         const unsigned char *p = dword_align (ptr);
1351                         int i;
1352                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
1353                         /* we could just store a pointer if we don't need to byteswap */
1354                         mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
1355                         for (i = 0; i < mh->num_clauses; ++i) {
1356                                 MonoExceptionClause *ec = &mh->clauses [i];
1357                                 if (is_fat) {
1358                                         /* we could memcpy and byteswap */
1359                                         ec->flags = read32 (p);
1360                                         p += 4;
1361                                         ec->try_offset = read32 (p);
1362                                         p += 4;
1363                                         ec->try_len = read32 (p);
1364                                         p += 4;
1365                                         ec->handler_offset = read32 (p);
1366                                         p += 4;
1367                                         ec->handler_len = read32 (p);
1368                                         p += 4;
1369                                         ec->token_or_filter = read32 (p);
1370                                         p += 4;
1371                                 } else {
1372                                         ec->flags = read16 (p);
1373                                         p += 2;
1374                                         ec->try_offset = read16 (p);
1375                                         p += 2;
1376                                         ec->try_len = *p;
1377                                         ++p;
1378                                         ec->handler_offset = read16 (p);
1379                                         p += 2;
1380                                         ec->handler_len = *p;
1381                                         ++p;
1382                                         ec->token_or_filter = read32 (p);
1383                                         p += 4;
1384                                 }
1385                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
1386                         }
1387                 }
1388                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
1389                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
1390                 else
1391                         return;
1392         }
1393 }
1394
1395 MonoMethodHeader *
1396 mono_metadata_parse_mh (MonoMetadata *m, const char *ptr)
1397 {
1398         MonoMethodHeader *mh;
1399         unsigned char flags = *(unsigned char *) ptr;
1400         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1401         guint16 fat_flags;
1402         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
1403         const unsigned char *code;
1404         int hsize;
1405         
1406         g_return_val_if_fail (ptr != NULL, NULL);
1407
1408         switch (format){
1409         case METHOD_HEADER_TINY_FORMAT:
1410                 mh = g_new0 (MonoMethodHeader, 1);
1411                 ptr++;
1412                 mh->max_stack = 8;
1413                 local_var_sig_tok = 0;
1414                 mh->code_size = flags >> 2;
1415                 mh->code = ptr;
1416                 return mh;
1417         case METHOD_HEADER_TINY_FORMAT1:
1418                 mh = g_new0 (MonoMethodHeader, 1);
1419                 ptr++;
1420                 mh->max_stack = 8;
1421                 local_var_sig_tok = 0;
1422
1423                 /*
1424                  * The spec claims 3 bits, but the Beta2 is
1425                  * incorrect
1426                  */
1427                 mh->code_size = flags >> 2;
1428                 mh->code = ptr;
1429                 return mh;
1430         case METHOD_HEADER_FAT_FORMAT:
1431                 fat_flags = read16 (ptr);
1432                 ptr += 2;
1433                 hsize = (fat_flags >> 12) & 0xf;
1434                 max_stack = read16 (ptr);
1435                 ptr += 2;
1436                 code_size = read32 (ptr);
1437                 ptr += 4;
1438                 local_var_sig_tok = read32 (ptr);
1439                 ptr += 4;
1440
1441                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1442                         init_locals = 1;
1443                 else
1444                         init_locals = 0;
1445
1446                 code = ptr;
1447
1448                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1449                         break;
1450
1451                 /*
1452                  * There are more sections
1453                  */
1454                 ptr = code + code_size;
1455                 
1456                 break;
1457                 
1458         default:
1459                 return NULL;
1460         }
1461                        
1462         if (local_var_sig_tok) {
1463                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
1464                 const char *ptr;
1465                 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
1466                 int len=0, i, bsize;
1467                 guint offset = 0;
1468
1469                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
1470                 ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
1471                 bsize = mono_metadata_decode_blob_size (ptr, &ptr);
1472                 if (*ptr != 0x07)
1473                         g_warning ("wrong signature for locals blob");
1474                 ptr++;
1475                 len = mono_metadata_decode_value (ptr, &ptr);
1476                 mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1477                 mh->num_locals = len;
1478                 for (i = 0; i < len; ++i) {
1479                         int val;
1480                         int align;
1481                         mh->locals [i] = mono_metadata_parse_type (m, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1482
1483                         val = mono_type_size (mh->locals [i], &align);
1484                         offset += align - 1;
1485                         offset &= ~(align - 1);
1486                         offset += val;
1487                 }
1488                 mh->locals_size = offset;
1489         } else {
1490                 mh = g_new0 (MonoMethodHeader, 1);
1491         }
1492         mh->code = code;
1493         mh->code_size = code_size;
1494         mh->max_stack = max_stack;
1495         mh->init_locals = init_locals;
1496         if (fat_flags & METHOD_HEADER_MORE_SECTS)
1497                 parse_section_data (mh, (const unsigned char*)ptr);
1498         return mh;
1499 }
1500
1501 void
1502 mono_metadata_free_mh (MonoMethodHeader *mh)
1503 {
1504         int i;
1505         for (i = 0; i < mh->num_locals; ++i)
1506                 mono_metadata_free_type (mh->locals[i]);
1507         g_free (mh->clauses);
1508         g_free (mh);
1509 }
1510
1511 /**
1512  * mono_metadata_parse_field_type:
1513  * @m: metadata context to extract information from
1514  * @ptr: pointer to the field signature
1515  *
1516  * Parses the field signature, and returns the type information for it. 
1517  *
1518  * Returns: The MonoType that was extracted from @ptr.
1519  */
1520 MonoType *
1521 mono_metadata_parse_field_type (MonoMetadata *m, short field_flags, const char *ptr, const char **rptr)
1522 {
1523         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
1524 }
1525
1526 MonoType *
1527 mono_metadata_parse_param (MonoMetadata *m, const char *ptr, const char **rptr)
1528 {
1529         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
1530 }
1531
1532 /*
1533  * mono_metadata_token_from_dor:
1534  * @dor_token: A TypeDefOrRef coded index
1535  *
1536  * dor_token is a TypeDefOrRef coded index: it contains either
1537  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
1538  * bits contain an index into the table.
1539  *
1540  * Returns: an expanded token
1541  */
1542 guint32
1543 mono_metadata_token_from_dor (guint32 dor_index)
1544 {
1545         guint32 table, idx;
1546
1547         table = dor_index & 0x03;
1548         idx = dor_index >> 2;
1549
1550         switch (table){
1551         case 0: /* TypeDef */
1552                 return MONO_TOKEN_TYPE_DEF | idx;
1553
1554         case 1: /* TypeRef */
1555                 return MONO_TOKEN_TYPE_REF | idx;
1556
1557         case 2: /* TypeSpec */
1558                 return MONO_TOKEN_TYPE_SPEC | idx;
1559
1560         default:
1561                 g_assert_not_reached ();
1562         }
1563
1564         return 0;
1565 }
1566
1567 /*
1568  * We use this to pass context information to the row locator
1569  */
1570 typedef struct {
1571         int idx;                        /* The index that we are trying to locate */
1572         int col_idx;            /* The index in the row where idx may be stored */
1573         MonoTableInfo *t;       /* pointer to the table */
1574         guint32 result;
1575 } locator_t;
1576
1577 #define CSIZE(x) (sizeof (x) / 4)
1578
1579 /*
1580  * How the row locator works.
1581  *
1582  *   Table A
1583  *   ___|___
1584  *   ___|___         Table B
1585  *   ___|___------>  _______
1586  *   ___|___         _______
1587  *   
1588  * A column in the rows of table A references an index in table B.
1589  * For example A may be the TYPEDEF table and B the METHODDEF table.
1590  * 
1591  * Given an index in table B we want to get the row in table A
1592  * where the column n references our index in B.
1593  *
1594  * In the locator_t structure:
1595  *      t is table A
1596  *      col_idx is the column number
1597  *      index is the index in table B
1598  *      result will be the index in table A
1599  *
1600  * Examples:
1601  * Table A              Table B         column (in table A)
1602  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
1603  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
1604  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
1605  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
1606  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
1607  *
1608  * Note that we still don't support encoded indexes.
1609  *
1610  */
1611 static int
1612 typedef_locator (const void *a, const void *b)
1613 {
1614         locator_t *loc = (locator_t *) a;
1615         char *bb = (char *) b;
1616         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
1617         guint32 col, col_next;
1618
1619         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
1620
1621         if (loc->idx < col)
1622                 return -1;
1623
1624         /*
1625          * Need to check that the next row is valid.
1626          */
1627         if (typedef_index + 1 < loc->t->rows) {
1628                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
1629                 if (loc->idx >= col_next)
1630                         return 1;
1631
1632                 if (col == col_next)
1633                         return 1; 
1634         }
1635
1636         loc->result = typedef_index;
1637         
1638         return 0;
1639 }
1640
1641 static int
1642 table_locator (const void *a, const void *b)
1643 {
1644         locator_t *loc = (locator_t *) a;
1645         char *bb = (char *) b;
1646         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
1647         guint32 col;
1648         
1649         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
1650
1651         if (loc->idx == col) {
1652                 loc->result = table_index;
1653                 return 0;
1654         }
1655         if (loc->idx < col)
1656                 return -1;
1657         else 
1658                 return 1;
1659 }
1660
1661 guint32
1662 mono_metadata_typedef_from_field (MonoMetadata *meta, guint32 index)
1663 {
1664         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1665         locator_t loc;
1666
1667         if (!tdef->base)
1668                 return 0;
1669
1670         loc.idx = mono_metadata_token_index (index);
1671         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
1672         loc.t = tdef;
1673
1674         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1675                 g_assert_not_reached ();
1676
1677         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1678         return loc.result + 1;
1679 }
1680
1681 guint32
1682 mono_metadata_typedef_from_method (MonoMetadata *meta, guint32 index)
1683 {
1684         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1685         locator_t loc;
1686         
1687         if (!tdef->base)
1688                 return 0;
1689
1690         loc.idx = mono_metadata_token_index (index);
1691         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
1692         loc.t = tdef;
1693
1694         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1695                 g_assert_not_reached ();
1696
1697         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1698         return loc.result + 1;
1699 }
1700
1701 MonoClass**
1702 mono_metadata_interfaces_from_typedef (MonoMetadata *meta, guint32 index, guint *count)
1703 {
1704         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
1705         locator_t loc;
1706         guint32 start, i;
1707         guint32 cols [MONO_INTERFACEIMPL_SIZE];
1708         MonoClass **result;
1709         
1710         *count = 0;
1711
1712         if (!tdef->base)
1713                 return NULL;
1714
1715         loc.idx = mono_metadata_token_index (index);
1716         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
1717         loc.t = tdef;
1718
1719         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
1720                 return NULL;
1721
1722         start = loc.result;
1723         /*
1724          * We may end up in the middle of the rows... 
1725          */
1726         while (start > 0) {
1727                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
1728                         start--;
1729                 else
1730                         break;
1731         }
1732         result = NULL;
1733         i = 0;
1734         while (start < tdef->rows) {
1735                 mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE);
1736                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
1737                         break;
1738                 result = g_renew (MonoClass*, result, i + 1);
1739                 result [i] = mono_class_get (meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]));
1740                 *count = ++i;
1741                 ++start;
1742         }
1743         return result;
1744 }
1745
1746 #ifndef __GNUC__
1747 #define __alignof__(a) sizeof(a)
1748 #endif
1749
1750 /*
1751  * mono_type_size:
1752  * @t: the type to return the size of
1753  *
1754  * Returns: the number of bytes required to hold an instance of this
1755  * type in memory
1756  */
1757 int
1758 mono_type_size (MonoType *t, gint *align)
1759 {
1760         if (!t) {
1761                 *align = 1;
1762                 return 0;
1763         }
1764         if (t->byref) {
1765                 *align = __alignof__(gpointer);
1766                 return sizeof (gpointer);
1767         }
1768
1769         switch (t->type){
1770         case MONO_TYPE_VOID:
1771                 *align = 1;
1772                 return 0;
1773         case MONO_TYPE_BOOLEAN:
1774                 *align = __alignof__(char);
1775                 return sizeof (char);
1776                 
1777         case MONO_TYPE_CHAR:
1778                 *align = __alignof__(short);
1779                 return sizeof (short);
1780                 
1781         case MONO_TYPE_I1:
1782         case MONO_TYPE_U1:
1783                 *align = __alignof__(char);
1784                 return 1;
1785                 
1786         case MONO_TYPE_I2:
1787         case MONO_TYPE_U2:
1788                 *align = __alignof__(gint16);
1789                 return 2;
1790                 
1791         case MONO_TYPE_I4:
1792         case MONO_TYPE_U4:
1793                 *align = __alignof__(gint32);
1794                 return 4;
1795         case MONO_TYPE_R4:
1796                 *align = __alignof__(float);
1797                 return 4;
1798                 
1799         case MONO_TYPE_I8:
1800         case MONO_TYPE_U8:
1801                 *align = __alignof__(gint64);
1802         case MONO_TYPE_R8:
1803                 *align = __alignof__(double);
1804                 return 8;
1805                 
1806         case MONO_TYPE_I:
1807         case MONO_TYPE_U:
1808                 *align = __alignof__(gpointer);
1809                 return sizeof (gpointer);
1810                 
1811         case MONO_TYPE_STRING:
1812                 *align = __alignof__(gpointer);
1813                 return sizeof (gpointer);
1814                 
1815         case MONO_TYPE_OBJECT:
1816                 *align = __alignof__(gpointer);
1817                 return sizeof (gpointer);
1818                 
1819         case MONO_TYPE_VALUETYPE: {
1820                 guint32 size;
1821
1822                 size = mono_class_value_size (t->data.klass, align);
1823                 return size;
1824         }
1825         case MONO_TYPE_CLASS:
1826         case MONO_TYPE_SZARRAY:
1827         case MONO_TYPE_PTR:
1828         case MONO_TYPE_FNPTR:
1829         case MONO_TYPE_ARRAY:
1830         case MONO_TYPE_TYPEDBYREF: /* we may want to use a struct {MonoType* type, void *data } instead ...*/
1831                 *align = __alignof__(gpointer);
1832                 return sizeof (gpointer);
1833         default:
1834                 g_error ("type 0x%02x unknown", t->type);
1835         }
1836         return 0;
1837 }
1838
1839 gboolean
1840 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
1841 {
1842         if (t1->type != t2->type ||
1843             t1->byref != t2->byref)
1844                 return FALSE;
1845
1846         switch (t1->type) {
1847         case MONO_TYPE_VOID:
1848         case MONO_TYPE_BOOLEAN:
1849         case MONO_TYPE_CHAR:
1850         case MONO_TYPE_I1:
1851         case MONO_TYPE_U1:
1852         case MONO_TYPE_I2:
1853         case MONO_TYPE_U2:
1854         case MONO_TYPE_I4:
1855         case MONO_TYPE_U4:
1856         case MONO_TYPE_I8:
1857         case MONO_TYPE_U8:
1858         case MONO_TYPE_R4:
1859         case MONO_TYPE_R8:
1860         case MONO_TYPE_STRING:
1861         case MONO_TYPE_I:
1862         case MONO_TYPE_U:
1863         case MONO_TYPE_OBJECT:
1864                 return TRUE;
1865         case MONO_TYPE_VALUETYPE:
1866         case MONO_TYPE_CLASS:
1867                 return t1->data.klass == t2->data.klass;
1868         case MONO_TYPE_SZARRAY:
1869                 return mono_metadata_type_equal (t1->data.type, t2->data.type);
1870         default:
1871                 g_error ("implement type compare for %0x!", t1->type);
1872                 return FALSE;
1873         }
1874
1875         return FALSE;
1876 }
1877
1878 gboolean
1879 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
1880 {
1881         int i;
1882
1883         if (sig1->hasthis != sig2->hasthis ||
1884             sig1->param_count != sig2->param_count)
1885                 return FALSE;
1886
1887         for (i = 0; i < sig1->param_count; i++) { 
1888                 MonoType *p1 = sig1->params[i];
1889                 MonoType *p2 = sig2->params[i];
1890                 
1891                 if (p1->attrs != p2->attrs)
1892                         return FALSE;
1893                 
1894                 if (!mono_metadata_type_equal (p1, p2))
1895                         return FALSE;
1896         }
1897
1898         return TRUE;
1899 }
1900
1901 void
1902 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
1903 {
1904         char *p = buf;
1905         
1906         if (value <= 127)
1907                 *p++ = value;
1908         else if (value <= 16384) {
1909                 p [0] = 0x80 | (value >> 8);
1910                 p [1] = value & 0xff;
1911                 p += 2;
1912         } else {
1913                 p [0] = (value >> 24) | 0xc0;
1914                 p [1] = (value >> 16) & 0xff;
1915                 p [2] = (value >> 8) & 0xff;
1916                 p [3] = value & 0xff;
1917                 p += 4;
1918         }
1919         if (endbuf)
1920                 *endbuf = p;
1921 }
1922
1923 /*
1924  * mono_metadata_field_info:
1925  * @meta: the Image the field is defined in
1926  * @index: the index in the field table representing the field
1927  * @offset: a pointer to an integer where to store the offset that 
1928  * may have been specified for the field in a FieldLayout table
1929  * @rva: a pointer to the address of the field data in the image that
1930  * may have been defined in a FieldRVA table
1931  * @marshal_info: a pointer to the marshal signature that may have been 
1932  * defined for the field in a FieldMarshal table.
1933  *
1934  * Gather info for field @index that may have been defined in the FieldLayout, 
1935  * FieldRVA and FieldMarshal tables.
1936  * Either of offset, rva and marshal_info can be NULL if you're not interested 
1937  * in the data.
1938  */
1939 void
1940 mono_metadata_field_info (MonoMetadata *meta, guint32 index, guint32 *offset, const char **rva, const char **marshal_info)
1941 {
1942         MonoTableInfo *tdef;
1943         locator_t loc;
1944
1945         loc.idx = index + 1;
1946         if (offset) {
1947                 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
1948
1949                 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
1950                 loc.t = tdef;
1951
1952                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
1953                         *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
1954                 } else {
1955                         *offset = (guint32)-1;
1956                 }
1957         }
1958         if (rva) {
1959                 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
1960
1961                 loc.col_idx = MONO_FIELD_RVA_FIELD;
1962                 loc.t = tdef;
1963
1964                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
1965                         /*
1966                          * LAMESPEC: There is no signature, no nothing, just the raw data.
1967                          */
1968                         *rva = mono_cli_rva_map (meta->image_info, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA));
1969                 } else {
1970                         *rva = NULL;
1971                 }
1972         }
1973
1974 }
1975
1976 /*
1977  * mono_metadata_get_constant_index:
1978  * @meta: the Image the field is defined in
1979  * @index: the token that may have a row defined in the constants table
1980  *
1981  * @token must be a FieldDef, ParamDef or PropertyDef token.
1982  *
1983  * Returns: the index into the Constsnts table or 0 if not found.
1984  */
1985 guint32
1986 mono_metadata_get_constant_index (MonoMetadata *meta, guint32 token)
1987 {
1988         MonoTableInfo *tdef;
1989         locator_t loc;
1990         guint32 index = mono_metadata_token_index (token);
1991
1992         tdef = &meta->tables [MONO_TABLE_CONSTANT];
1993         index <<= HASCOSTANT_BITS;
1994         switch (mono_metadata_token_table (token)) {
1995         case MONO_TABLE_FIELD:
1996                 index |= HASCOSTANT_FIEDDEF;
1997                 break;
1998         case MONO_TABLE_PARAM:
1999                 index |= HASCOSTANT_PARAM;
2000                 break;
2001         case MONO_TABLE_PROPERTY:
2002                 index |= HASCOSTANT_PROPERTY;
2003                 break;
2004         default:
2005                 g_warning ("Not a valid token for the constant table: 0x%08x", token);
2006                 return 0;
2007         }
2008         loc.idx = index;
2009         loc.col_idx = MONO_CONSTANT_PARENT;
2010         loc.t = tdef;
2011
2012         if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
2013                 return loc.result + 1;
2014         }
2015         return 0;
2016 }
2017