Mon Aug 27 20:12:01 CEST 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 "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 = 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         guint table;
914         token = mono_metadata_decode_value (ptr, &ptr);
915
916         switch (token & 0x03) {
917         case 0: table = MONO_TABLE_TYPEDEF; break;
918         case 1: table = MONO_TABLE_TYPEREF; break;
919         case 2: table = MONO_TABLE_TYPESPEC; break;
920         default: g_error ("Unhandled encoding for typedef-or-ref coded index");
921         }
922         if (rptr)
923                 *rptr = ptr;
924         return (token >> 2) | table << 24;
925 }
926
927 int
928 mono_metadata_parse_custom_mod (MonoMetadata *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
929 {
930         MonoCustomMod local;
931         if ((*ptr == MONO_TYPE_CMOD_OPT) ||
932             (*ptr == MONO_TYPE_CMOD_REQD)) {
933                 if (!dest)
934                         dest = &local;
935                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
936                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, &ptr);
937                 return TRUE;
938         }
939         return FALSE;
940 }
941
942 MonoArray *
943 mono_metadata_parse_array (MonoMetadata *m, const char *ptr, const char **rptr)
944 {
945         int i;
946         MonoArray *array = g_new0 (MonoArray, 1);
947         
948         array->type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
949         array->rank = mono_metadata_decode_value (ptr, &ptr);
950
951         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
952         if (array->numsizes)
953                 array->sizes = g_new0 (int, array->numsizes);
954         for (i = 0; i < array->numsizes; ++i)
955                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
956
957         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
958         if (array->numlobounds)
959                 array->lobounds = g_new0 (int, array->numlobounds);
960         for (i = 0; i < array->numlobounds; ++i)
961                 array->lobounds [i] = mono_metadata_decode_value (ptr, &ptr);
962
963         if (rptr)
964                 *rptr = ptr;
965         return array;
966 }
967
968 void
969 mono_metadata_free_array (MonoArray *array)
970 {
971         mono_metadata_free_type (array->type);
972         g_free (array->sizes);
973         g_free (array->lobounds);
974         g_free (array);
975 }
976
977 /*
978  * need to add common field and param attributes combinations:
979  * [out] param
980  * public static
981  * public static literal
982  * private
983  * private static
984  * private static literal
985  */
986 static MonoType
987 builtin_types[] = {
988         /* data, attrs, type,              nmods, byref, pinned */
989         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
990         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
991         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
992         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
993         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
994         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
995         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
996         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
997         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
998         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
999         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1000         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1001         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1002         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1003         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1004         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1005         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1006         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1007         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1008         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1009         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1010         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1011         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1012         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1013         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1014         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1015         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1016         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1017         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1018         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1019         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1020         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1021         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1022         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0}
1023 };
1024
1025 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1026
1027 static GHashTable *type_cache = NULL;
1028
1029 /*
1030  * MonoTypes with modifies are never cached, so we never check or use that field.
1031  */
1032 static int
1033 mono_type_hash (MonoType *type)
1034 {
1035         return type->type | (type->byref << 8) | (type->attrs << 9);
1036 }
1037
1038 static gboolean
1039 mono_type_equal (MonoType *a, MonoType *b)
1040 {
1041         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1042                 return 0;
1043         /* need other checks */
1044         return 1;
1045 }
1046
1047 MonoType*
1048 mono_metadata_parse_type (MonoMetadata *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr)
1049 {
1050         MonoType *type, *cached;
1051
1052         if (!type_cache) {
1053                 int i;
1054                 type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1055                 for (i=0; i < NBUILTIN_TYPES (); ++i)
1056                         g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
1057         }
1058
1059         switch (mode) {
1060         case MONO_PARSE_MOD_TYPE:
1061         case MONO_PARSE_PARAM:
1062         case MONO_PARSE_RET:
1063         case MONO_PARSE_FIELD: {
1064                 /* count the modifiers */
1065                 const char *tmp_ptr = ptr;
1066                 int count = 0;
1067                 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1068                         count++;
1069                 if (count) {
1070                         type = g_malloc0 (sizeof (MonoType) + (count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
1071                         type->num_mods = count;
1072                         if (count > 64)
1073                                 g_warning ("got more than 64 modifiers in type");
1074                         /* save them this time */
1075                         count = 0;
1076                         while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr))
1077                                 count++;
1078                         break;
1079                 } /* fall through */
1080         }
1081         case MONO_PARSE_LOCAL:
1082         case MONO_PARSE_TYPE:
1083                 /*
1084                  * Later we can avoid doing this allocation.
1085                  */
1086                 type = g_new0 (MonoType, 1);
1087                 break;
1088         default:
1089                 g_assert_not_reached ();
1090         }
1091         
1092         type->attrs = opt_attrs;
1093         if (mode == MONO_PARSE_LOCAL) {
1094                 /*
1095                  * check for pinned flag
1096                  */
1097                 if (*ptr == MONO_TYPE_PINNED) {
1098                         type->pinned = 1;
1099                         ++ptr;
1100                 }
1101         }
1102
1103         switch (*ptr) {
1104         case MONO_TYPE_BYREF: 
1105                 if (mode == MONO_PARSE_FIELD)
1106                         g_warning ("A field type cannot be byref");
1107                 type->byref = 1; 
1108                 ptr++;
1109                 /* follow through */
1110         default:
1111                 /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET)
1112                         g_error ("void not allowed in param");*/
1113                 do_mono_metadata_parse_type (type, m, ptr, &ptr);
1114                 break;
1115         }
1116         if (rptr)
1117                 *rptr = ptr;
1118         if (mode != MONO_PARSE_PARAM && !type->num_mods && (cached = g_hash_table_lookup (type_cache, type))) {
1119                 mono_metadata_free_type (type);
1120                 return cached;
1121         } else {
1122                 return type;
1123         }
1124 }
1125
1126 MonoMethodSignature *
1127 mono_metadata_parse_method_signature (MonoMetadata *m, int def, const char *ptr, const char **rptr)
1128 {
1129         MonoMethodSignature *method;
1130         int i, align, offset = 0;
1131         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1132
1133         if (*ptr & 0x20)
1134                 hasthis = 1;
1135         if (*ptr & 0x40)
1136                 explicit_this = 1;
1137         call_convention = *ptr & 0x0F;
1138         ptr++;
1139         param_count = mono_metadata_decode_value (ptr, &ptr);
1140
1141         method = g_malloc0 (sizeof (MonoMethodSignature) + (param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1142         method->param_count = param_count;
1143         method->hasthis = hasthis;
1144         method->explicit_this = explicit_this;
1145         method->call_convention = call_convention;
1146         method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, 0, ptr, &ptr);
1147
1148         if (method->hasthis)
1149                 offset += sizeof(gpointer);
1150         if (method->param_count) {
1151                 int size;
1152                 
1153                 method->sentinelpos = -1;
1154                 
1155                 for (i = 0; i < method->param_count; ++i) {
1156                         if (*ptr == MONO_TYPE_SENTINEL) {
1157                                 if (method->call_convention != MONO_CALL_VARARG || def)
1158                                                 g_error ("found sentinel for methoddef or no vararg method");
1159                                 method->sentinelpos = i;
1160                                 ptr++;
1161                         }
1162                         method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, &ptr);
1163                         size = mono_type_size (method->params [i], &align);
1164                         offset += (offset % align);
1165                         offset += size;
1166                 }
1167         }
1168         method->params_size = offset;
1169
1170         if (rptr)
1171                 *rptr = ptr;
1172         /*
1173          * Add signature to a cache and increase ref count...
1174          */
1175         return method;
1176 }
1177
1178 void
1179 mono_metadata_free_method_signature (MonoMethodSignature *method)
1180 {
1181         int i;
1182         mono_metadata_free_type (method->ret);
1183         for (i = 0; i < method->param_count; ++i)
1184                 mono_metadata_free_type (method->params [i]);
1185
1186         g_free (method);
1187 }
1188
1189 /* 
1190  * do_mono_metadata_parse_type:
1191  * @type: MonoType to be filled in with the return value
1192  * @
1193  * Internal routine used to "fill" the contents of @type from an 
1194  * allocated pointer.  This is done this way to avoid doing too
1195  * many mini-allocations (particularly for the MonoFieldType which
1196  * most of the time is just a MonoType, but sometimes might be augmented).
1197  *
1198  * This routine is used by mono_metadata_parse_type and
1199  * mono_metadata_parse_field_type
1200  *
1201  * This extracts a Type as specified in Partition II (22.2.12) 
1202  */
1203 static void
1204 do_mono_metadata_parse_type (MonoType *type, MonoMetadata *m, const char *ptr, const char **rptr)
1205 {
1206         type->type = mono_metadata_decode_value (ptr, &ptr);
1207         
1208         switch (type->type){
1209         case MONO_TYPE_VOID:
1210         case MONO_TYPE_BOOLEAN:
1211         case MONO_TYPE_CHAR:
1212         case MONO_TYPE_I1:
1213         case MONO_TYPE_U1:
1214         case MONO_TYPE_I2:
1215         case MONO_TYPE_U2:
1216         case MONO_TYPE_I4:
1217         case MONO_TYPE_U4:
1218         case MONO_TYPE_I8:
1219         case MONO_TYPE_U8:
1220         case MONO_TYPE_R4:
1221         case MONO_TYPE_R8:
1222         case MONO_TYPE_I:
1223         case MONO_TYPE_U:
1224         case MONO_TYPE_STRING:
1225         case MONO_TYPE_OBJECT:
1226         case MONO_TYPE_TYPEDBYREF:
1227                 break;
1228         case MONO_TYPE_VALUETYPE:
1229         case MONO_TYPE_CLASS: {
1230                 guint32 token;
1231                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1232                 type->data.klass = mono_class_get (m, token);
1233                 break;
1234         }
1235         case MONO_TYPE_SZARRAY:
1236         case MONO_TYPE_PTR:
1237                 type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
1238                 break;
1239         case MONO_TYPE_FNPTR:
1240                 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1241                 break;
1242         case MONO_TYPE_ARRAY:
1243                 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1244                 break;
1245         default:
1246                 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1247         }
1248         
1249         if (rptr)
1250                 *rptr = ptr;
1251 }
1252
1253 #if 0
1254 /**
1255  * mono_metadata_parse_type:
1256  * @m: metadata context to scan
1257  * @ptr: pointer to encoded Type stream.
1258  * @rptr: the new position in the stream after parsing the type
1259  *
1260  * Returns: A MonoType structure that has the parsed information
1261  * from the type stored at @ptr in the metadata table @m.
1262  */
1263 MonoType *
1264 mono_metadata_parse_type (MonoMetadata *m, const char *ptr, const char **rptr)
1265 {
1266         /* should probably be allocated in a memchunk */
1267         MonoType *type = g_new0(MonoType, 1);
1268
1269         do_mono_metadata_parse_type (type, m, ptr, rptr);
1270
1271         return type;
1272 }
1273 #endif
1274
1275 void
1276 mono_metadata_free_type (MonoType *type)
1277 {
1278         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
1279                 return;
1280         switch (type->type){
1281         case MONO_TYPE_SZARRAY:
1282         case MONO_TYPE_PTR:
1283                 mono_metadata_free_type (type->data.type);
1284                 break;
1285         case MONO_TYPE_FNPTR:
1286                 mono_metadata_free_method_signature (type->data.method);
1287                 break;
1288         case MONO_TYPE_ARRAY:
1289                 mono_metadata_free_array (type->data.array);
1290                 break;
1291         }
1292         g_free (type);
1293 }
1294
1295 static void
1296 hex_dump (const char *buffer, int base, int count)
1297 {
1298         int show_header = 1;
1299         int i;
1300
1301         if (count < 0){
1302                 count = -count;
1303                 show_header = 0;
1304         }
1305         
1306         for (i = 0; i < count; i++){
1307                 if (show_header)
1308                         if ((i % 16) == 0)
1309                                 printf ("\n0x%08x: ", (unsigned char) base + i);
1310
1311                 printf ("%02x ", (unsigned char) (buffer [i]));
1312         }
1313         fflush (stdout);
1314 }
1315
1316 /** 
1317  * @mh: The Method header
1318  * @ptr: Points to the beginning of the Section Data (25.3)
1319  */
1320 static void
1321 parse_section_data (MonoMethodHeader *mh, const unsigned char *ptr)
1322 {
1323         unsigned char sect_data_flags;
1324         const unsigned char *sptr;
1325         int is_fat;
1326         guint32 sect_data_len;
1327         
1328         while (1) {
1329                 /* align on 32-bit boundary */
1330                 /* FIXME: not 64-bit clean code */
1331                 sptr = ptr = dword_align (ptr); 
1332                 sect_data_flags = *ptr;
1333                 ptr++;
1334                 
1335                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1336                 if (is_fat) {
1337                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
1338                         ptr += 3;
1339                 } else {
1340                         sect_data_len = ptr [0];
1341                         ++ptr;
1342                 }
1343                 /*
1344                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
1345                 hex_dump (sptr, 0, sect_data_len+8);
1346                 g_print ("\nheader: ");
1347                 hex_dump (sptr-4, 0, 4);
1348                 g_print ("\n");
1349                 */
1350                 
1351                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1352                         const unsigned char *p = dword_align (ptr);
1353                         int i;
1354                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
1355                         /* we could just store a pointer if we don't need to byteswap */
1356                         mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
1357                         for (i = 0; i < mh->num_clauses; ++i) {
1358                                 MonoExceptionClause *ec = &mh->clauses [i];
1359                                 if (is_fat) {
1360                                         /* we could memcpy and byteswap */
1361                                         ec->flags = read32 (p);
1362                                         p += 4;
1363                                         ec->try_offset = read32 (p);
1364                                         p += 4;
1365                                         ec->try_len = read32 (p);
1366                                         p += 4;
1367                                         ec->handler_offset = read32 (p);
1368                                         p += 4;
1369                                         ec->handler_len = read32 (p);
1370                                         p += 4;
1371                                         ec->token_or_filter = read32 (p);
1372                                         p += 4;
1373                                 } else {
1374                                         ec->flags = read16 (p);
1375                                         p += 2;
1376                                         ec->try_offset = read16 (p);
1377                                         p += 2;
1378                                         ec->try_len = *p;
1379                                         ++p;
1380                                         ec->handler_offset = read16 (p);
1381                                         p += 2;
1382                                         ec->handler_len = *p;
1383                                         ++p;
1384                                         ec->token_or_filter = read32 (p);
1385                                         p += 4;
1386                                 }
1387                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
1388                         }
1389                 }
1390                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
1391                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
1392                 else
1393                         return;
1394         }
1395 }
1396
1397 MonoMethodHeader *
1398 mono_metadata_parse_mh (MonoMetadata *m, const char *ptr)
1399 {
1400         MonoMethodHeader *mh;
1401         unsigned char flags = *(unsigned char *) ptr;
1402         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1403         guint16 fat_flags;
1404         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
1405         const unsigned char *code;
1406         int hsize;
1407         
1408         g_return_val_if_fail (ptr != NULL, NULL);
1409
1410         switch (format){
1411         case METHOD_HEADER_TINY_FORMAT:
1412                 mh = g_new0 (MonoMethodHeader, 1);
1413                 ptr++;
1414                 mh->max_stack = 8;
1415                 local_var_sig_tok = 0;
1416                 mh->code_size = flags >> 2;
1417                 mh->code = ptr;
1418                 return mh;
1419         case METHOD_HEADER_TINY_FORMAT1:
1420                 mh = g_new0 (MonoMethodHeader, 1);
1421                 ptr++;
1422                 mh->max_stack = 8;
1423                 local_var_sig_tok = 0;
1424
1425                 //
1426                 // The spec claims 3 bits, but the Beta2 is
1427                 // incorrect
1428                 //
1429                 mh->code_size = flags >> 2;
1430                 mh->code = ptr;
1431                 return mh;
1432         case METHOD_HEADER_FAT_FORMAT:
1433                 fat_flags = read16 (ptr);
1434                 ptr += 2;
1435                 hsize = (fat_flags >> 12) & 0xf;
1436                 max_stack = read16 (ptr);
1437                 ptr += 2;
1438                 code_size = read32 (ptr);
1439                 ptr += 4;
1440                 local_var_sig_tok = read32 (ptr);
1441                 ptr += 4;
1442
1443                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1444                         init_locals = 1;
1445                 else
1446                         init_locals = 0;
1447
1448                 code = ptr;
1449
1450                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1451                         break;
1452
1453                 /*
1454                  * There are more sections
1455                  */
1456                 ptr = code + code_size;
1457                 
1458                 break;
1459                 
1460         default:
1461                 return NULL;
1462         }
1463                        
1464         if (local_var_sig_tok) {
1465                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
1466                 const char *ptr;
1467                 guint32 cols [MONO_STAND_ALONG_SIGNATURE_SIZE];
1468                 int len=0, i, bsize;
1469                 guint offset = 0;
1470
1471                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
1472                 ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONG_SIGNATURE]);
1473                 bsize = mono_metadata_decode_blob_size (ptr, &ptr);
1474                 if (*ptr != 0x07)
1475                         g_warning ("wrong signature for locals blob");
1476                 ptr++;
1477                 len = mono_metadata_decode_value (ptr, &ptr);
1478                 mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1479                 mh->num_locals = len;
1480                 for (i = 0; i < len; ++i) {
1481                         int val;
1482                         int align;
1483                         mh->locals [i] = mono_metadata_parse_type (m, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1484
1485                         val = mono_type_size (mh->locals [i], &align);
1486                         offset += (offset % align);
1487                         offset += val;
1488                 }
1489                 mh->locals_size = offset;
1490         } else {
1491                 mh = g_new0 (MonoMethodHeader, 1);
1492         }
1493         mh->code = code;
1494         mh->code_size = code_size;
1495         mh->max_stack = max_stack;
1496         mh->init_locals = init_locals;
1497         if (fat_flags & METHOD_HEADER_MORE_SECTS)
1498                 parse_section_data (mh, (const unsigned char*)ptr);
1499         return mh;
1500 }
1501
1502 void
1503 mono_metadata_free_mh (MonoMethodHeader *mh)
1504 {
1505         int i;
1506         for (i = 0; i < mh->num_locals; ++i)
1507                 mono_metadata_free_type (mh->locals[i]);
1508         g_free (mh->clauses);
1509         g_free (mh);
1510 }
1511
1512 /**
1513  * mono_metadata_parse_field_type:
1514  * @m: metadata context to extract information from
1515  * @ptr: pointer to the field signature
1516  *
1517  * Parses the field signature, and returns the type information for it. 
1518  *
1519  * Returns: The MonoType that was extracted from @ptr.
1520  */
1521 MonoType *
1522 mono_metadata_parse_field_type (MonoMetadata *m, short field_flags, const char *ptr, const char **rptr)
1523 {
1524         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
1525 }
1526
1527 MonoType *
1528 mono_metadata_parse_param (MonoMetadata *m, const char *ptr, const char **rptr)
1529 {
1530         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
1531 }
1532
1533 /*
1534  * mono_metadata_token_from_dor:
1535  * @dor_token: A TypeDefOrRef coded index
1536  *
1537  * dor_token is a TypeDefOrRef coded index: it contains either
1538  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
1539  * bits contain an index into the table.
1540  *
1541  * Returns: an expanded token
1542  */
1543 guint32
1544 mono_metadata_token_from_dor (guint32 dor_index)
1545 {
1546         int table, idx;
1547
1548         table = dor_index & 0x03;
1549         idx = dor_index >> 2;
1550
1551         switch (table){
1552         case 0: /* TypeDef */
1553                 return MONO_TOKEN_TYPE_DEF | idx;
1554
1555         case 1: /* TypeRef */
1556                 return MONO_TOKEN_TYPE_REF | idx;
1557
1558         case 2: /* TypeSpec */
1559                 return MONO_TOKEN_TYPE_SPEC | idx;
1560
1561         default:
1562                 g_assert_not_reached ();
1563         }
1564
1565         return 0;
1566 }
1567
1568 /*
1569  * We use this to pass context information to the row locator
1570  */
1571 typedef struct {
1572         int idx;                        /* The index that we are trying to locate */
1573         int col_idx;            /* The index in the row where idx may be stored */
1574         MonoTableInfo *t;       /* pointer to the table */
1575         guint32 result;
1576 } locator_t;
1577
1578 #define CSIZE(x) (sizeof (x) / 4)
1579
1580 /*
1581  * How the row locator works.
1582  *
1583  *   Table A
1584  *   ___|___
1585  *   ___|___         Table B
1586  *   ___|___------>  _______
1587  *   ___|___         _______
1588  *   
1589  * A column in the rows of table A references an index in table B.
1590  * For example A may be the TYPEDEF table and B the METHODDEF table.
1591  * 
1592  * Given an index in table B we want to get the row in table A
1593  * where the column n references our index in B.
1594  *
1595  * In the locator_t structure:
1596  *      t is table A
1597  *      col_idx is the column number
1598  *      index is the index in table B
1599  *      result will be the index in table A
1600  *
1601  * Examples:
1602  * Table A              Table B         column (in table A)
1603  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
1604  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
1605  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
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 guint32
1642 mono_metadata_typedef_from_field (MonoMetadata *meta, guint32 index)
1643 {
1644         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1645         locator_t loc;
1646         
1647         loc.idx = mono_metadata_token_index (index);
1648         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
1649         loc.t = tdef;
1650
1651         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1652                 g_assert_not_reached ();
1653
1654         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1655         return loc.result + 1;
1656 }
1657
1658 guint32
1659 mono_metadata_typedef_from_method (MonoMetadata *meta, guint32 index)
1660 {
1661         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1662         locator_t loc;
1663         
1664         loc.idx = mono_metadata_token_index (index);
1665         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
1666         loc.t = tdef;
1667
1668         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1669                 g_assert_not_reached ();
1670
1671         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1672         return loc.result + 1;
1673 }
1674
1675 #ifndef __GNUC__
1676 #define __alignof__(a) sizeof(a)
1677 #endif
1678
1679 /*
1680  * mono_type_size:
1681  * @t: the type to return the size of
1682  *
1683  * Returns: the number of bytes required to hold an instance of this
1684  * type in memory
1685  */
1686 int
1687 mono_type_size (MonoType *t, gint *align)
1688 {
1689         if (!t) {
1690                 *align = 1;
1691                 return 0;
1692         }
1693         if (t->byref) {
1694                 *align = __alignof__(gpointer);
1695                 return sizeof (gpointer);
1696         }
1697
1698         switch (t->type){
1699         case MONO_TYPE_VOID:
1700                 *align = 1;
1701                 return 0;
1702         case MONO_TYPE_BOOLEAN:
1703                 *align = __alignof__(char);
1704                 return sizeof (char);
1705                 
1706         case MONO_TYPE_CHAR:
1707                 *align = __alignof__(short);
1708                 return sizeof (short);
1709                 
1710         case MONO_TYPE_I1:
1711         case MONO_TYPE_U1:
1712                 *align = __alignof__(char);
1713                 return 1;
1714                 
1715         case MONO_TYPE_I2:
1716         case MONO_TYPE_U2:
1717                 *align = __alignof__(gint16);
1718                 return 2;
1719                 
1720         case MONO_TYPE_I4:
1721         case MONO_TYPE_U4:
1722                 *align = __alignof__(gint32);
1723                 return 4;
1724         case MONO_TYPE_R4:
1725                 *align = __alignof__(float);
1726                 return 4;
1727                 
1728         case MONO_TYPE_I8:
1729         case MONO_TYPE_U8:
1730                 *align = __alignof__(gint64);
1731         case MONO_TYPE_R8:
1732                 *align = __alignof__(double);
1733                 return 8;
1734                 
1735         case MONO_TYPE_I:
1736         case MONO_TYPE_U:
1737                 *align = __alignof__(gpointer);
1738                 return sizeof (gpointer);
1739                 
1740         case MONO_TYPE_STRING:
1741                 *align = __alignof__(gpointer);
1742                 return sizeof (gpointer);
1743                 
1744         case MONO_TYPE_OBJECT:
1745                 *align = __alignof__(gpointer);
1746                 return sizeof (gpointer);
1747                 
1748         case MONO_TYPE_VALUETYPE: {
1749                 guint32 size;
1750
1751                 size = mono_class_value_size (t->data.klass, align);
1752                 return size;
1753         }
1754         case MONO_TYPE_CLASS:
1755         case MONO_TYPE_SZARRAY:
1756         case MONO_TYPE_PTR:
1757         case MONO_TYPE_FNPTR:
1758         case MONO_TYPE_ARRAY:
1759         case MONO_TYPE_TYPEDBYREF: /* we may want to use a struct {MonoType* type, void *data } instead ...*/
1760                 *align = __alignof__(gpointer);
1761                 return sizeof (gpointer);
1762         default:
1763                 g_error ("type 0x%02x unknown", t->type);
1764         }
1765         return 0;
1766 }
1767
1768 gboolean
1769 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
1770 {
1771         if (t1->type != t2->type ||
1772             t1->byref != t2->byref)
1773                 return FALSE;
1774
1775         switch (t1->type) {
1776         case MONO_TYPE_VOID:
1777         case MONO_TYPE_BOOLEAN:
1778         case MONO_TYPE_CHAR:
1779         case MONO_TYPE_I1:
1780         case MONO_TYPE_U1:
1781         case MONO_TYPE_I2:
1782         case MONO_TYPE_U2:
1783         case MONO_TYPE_I4:
1784         case MONO_TYPE_U4:
1785         case MONO_TYPE_I8:
1786         case MONO_TYPE_U8:
1787         case MONO_TYPE_R4:
1788         case MONO_TYPE_R8:
1789         case MONO_TYPE_STRING:
1790         case MONO_TYPE_I:
1791         case MONO_TYPE_U:
1792         case MONO_TYPE_OBJECT:
1793                 break;
1794         case MONO_TYPE_VALUETYPE:
1795         case MONO_TYPE_CLASS:
1796         case MONO_TYPE_SZARRAY:
1797                 return t1->data.klass == t2->data.klass;
1798         default:
1799                 g_error ("implement type compare for %0x!", t1->type);
1800                 return FALSE;
1801         }
1802
1803         return TRUE;
1804 }
1805
1806 gboolean
1807 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
1808 {
1809         int i;
1810
1811         if (sig1->hasthis != sig2->hasthis ||
1812             sig1->param_count != sig2->param_count)
1813                 return FALSE;
1814
1815         for (i = 0; i < sig1->param_count; i++) { 
1816                 MonoType *p1 = sig1->params[i];
1817                 MonoType *p2 = sig2->params[i];
1818                 
1819                 if (p1->attrs != p2->attrs)
1820                         return FALSE;
1821                 
1822                 if (!mono_metadata_type_equal (p1, p2))
1823                         return FALSE;
1824         }
1825
1826         return TRUE;
1827 }
1828