Fix make distcheck.
[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, MonoImage *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 (MonoImage *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                         n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
505                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
506                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
507                         n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *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 (MonoImage *m, int def, const char *ptr, const char **rptr)
1125 {
1126         MonoMethodSignature *method;
1127         int i;
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->param_count) {
1146                 method->sentinelpos = -1;
1147                 
1148                 for (i = 0; i < method->param_count; ++i) {
1149                         if (*ptr == MONO_TYPE_SENTINEL) {
1150                                 if (method->call_convention != MONO_CALL_VARARG || def)
1151                                                 g_error ("found sentinel for methoddef or no vararg method");
1152                                 method->sentinelpos = i;
1153                                 ptr++;
1154                         }
1155                         method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, &ptr);
1156                 }
1157         }
1158
1159         if (rptr)
1160                 *rptr = ptr;
1161         /*
1162          * Add signature to a cache and increase ref count...
1163          */
1164         return method;
1165 }
1166
1167 void
1168 mono_metadata_free_method_signature (MonoMethodSignature *method)
1169 {
1170         int i;
1171         mono_metadata_free_type (method->ret);
1172         for (i = 0; i < method->param_count; ++i)
1173                 mono_metadata_free_type (method->params [i]);
1174
1175         g_free (method);
1176 }
1177
1178 /* 
1179  * do_mono_metadata_parse_type:
1180  * @type: MonoType to be filled in with the return value
1181  * @
1182  * Internal routine used to "fill" the contents of @type from an 
1183  * allocated pointer.  This is done this way to avoid doing too
1184  * many mini-allocations (particularly for the MonoFieldType which
1185  * most of the time is just a MonoType, but sometimes might be augmented).
1186  *
1187  * This routine is used by mono_metadata_parse_type and
1188  * mono_metadata_parse_field_type
1189  *
1190  * This extracts a Type as specified in Partition II (22.2.12) 
1191  */
1192 static void
1193 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, const char **rptr)
1194 {
1195         type->type = mono_metadata_decode_value (ptr, &ptr);
1196         
1197         switch (type->type){
1198         case MONO_TYPE_VOID:
1199         case MONO_TYPE_BOOLEAN:
1200         case MONO_TYPE_CHAR:
1201         case MONO_TYPE_I1:
1202         case MONO_TYPE_U1:
1203         case MONO_TYPE_I2:
1204         case MONO_TYPE_U2:
1205         case MONO_TYPE_I4:
1206         case MONO_TYPE_U4:
1207         case MONO_TYPE_I8:
1208         case MONO_TYPE_U8:
1209         case MONO_TYPE_R4:
1210         case MONO_TYPE_R8:
1211         case MONO_TYPE_I:
1212         case MONO_TYPE_U:
1213         case MONO_TYPE_STRING:
1214         case MONO_TYPE_OBJECT:
1215         case MONO_TYPE_TYPEDBYREF:
1216                 break;
1217         case MONO_TYPE_VALUETYPE:
1218         case MONO_TYPE_CLASS: {
1219                 guint32 token;
1220                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1221                 type->data.klass = mono_class_get (m, token);
1222                 break;
1223         }
1224         case MONO_TYPE_SZARRAY:
1225         case MONO_TYPE_PTR:
1226                 type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
1227                 break;
1228         case MONO_TYPE_FNPTR:
1229                 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1230                 break;
1231         case MONO_TYPE_ARRAY:
1232                 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1233                 break;
1234         default:
1235                 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1236         }
1237         
1238         if (rptr)
1239                 *rptr = ptr;
1240 }
1241
1242 #if 0
1243 /**
1244  * mono_metadata_parse_type:
1245  * @m: metadata context to scan
1246  * @ptr: pointer to encoded Type stream.
1247  * @rptr: the new position in the stream after parsing the type
1248  *
1249  * Returns: A MonoType structure that has the parsed information
1250  * from the type stored at @ptr in the metadata table @m.
1251  */
1252 MonoType *
1253 mono_metadata_parse_type (MonoImage *m, const char *ptr, const char **rptr)
1254 {
1255         /* should probably be allocated in a memchunk */
1256         MonoType *type = g_new0(MonoType, 1);
1257
1258         do_mono_metadata_parse_type (type, m, ptr, rptr);
1259
1260         return type;
1261 }
1262 #endif
1263
1264 void
1265 mono_metadata_free_type (MonoType *type)
1266 {
1267         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
1268                 return;
1269         switch (type->type){
1270         case MONO_TYPE_SZARRAY:
1271         case MONO_TYPE_PTR:
1272                 mono_metadata_free_type (type->data.type);
1273                 break;
1274         case MONO_TYPE_FNPTR:
1275                 mono_metadata_free_method_signature (type->data.method);
1276                 break;
1277         case MONO_TYPE_ARRAY:
1278                 mono_metadata_free_array (type->data.array);
1279                 break;
1280         }
1281         g_free (type);
1282 }
1283
1284 static void
1285 hex_dump (const char *buffer, int base, int count)
1286 {
1287         int show_header = 1;
1288         int i;
1289
1290         if (count < 0){
1291                 count = -count;
1292                 show_header = 0;
1293         }
1294         
1295         for (i = 0; i < count; i++){
1296                 if (show_header)
1297                         if ((i % 16) == 0)
1298                                 printf ("\n0x%08x: ", (unsigned char) base + i);
1299
1300                 printf ("%02x ", (unsigned char) (buffer [i]));
1301         }
1302         fflush (stdout);
1303 }
1304
1305 /** 
1306  * @mh: The Method header
1307  * @ptr: Points to the beginning of the Section Data (25.3)
1308  */
1309 static void
1310 parse_section_data (MonoMethodHeader *mh, const unsigned char *ptr)
1311 {
1312         unsigned char sect_data_flags;
1313         const unsigned char *sptr;
1314         int is_fat;
1315         guint32 sect_data_len;
1316         
1317         while (1) {
1318                 /* align on 32-bit boundary */
1319                 /* FIXME: not 64-bit clean code */
1320                 sptr = ptr = dword_align (ptr); 
1321                 sect_data_flags = *ptr;
1322                 ptr++;
1323                 
1324                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1325                 if (is_fat) {
1326                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
1327                         ptr += 3;
1328                 } else {
1329                         sect_data_len = ptr [0];
1330                         ++ptr;
1331                 }
1332                 /*
1333                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
1334                 hex_dump (sptr, 0, sect_data_len+8);
1335                 g_print ("\nheader: ");
1336                 hex_dump (sptr-4, 0, 4);
1337                 g_print ("\n");
1338                 */
1339                 
1340                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1341                         const unsigned char *p = dword_align (ptr);
1342                         int i;
1343                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
1344                         /* we could just store a pointer if we don't need to byteswap */
1345                         mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
1346                         for (i = 0; i < mh->num_clauses; ++i) {
1347                                 MonoExceptionClause *ec = &mh->clauses [i];
1348
1349                                 if (is_fat) {
1350                                         /* we could memcpy and byteswap */
1351                                         ec->flags = read32 (p);
1352                                         p += 4;
1353                                         ec->try_offset = read32 (p);
1354                                         p += 4;
1355                                         ec->try_len = read32 (p);
1356                                         p += 4;
1357                                         ec->handler_offset = read32 (p);
1358                                         p += 4;
1359                                         ec->handler_len = read32 (p);
1360                                         p += 4;
1361                                         ec->token_or_filter = read32 (p);
1362                                         p += 4;
1363                                 } else {
1364                                         ec->flags = read16 (p);
1365                                         p += 2;
1366                                         ec->try_offset = read16 (p);
1367                                         p += 2;
1368                                         ec->try_len = *p;
1369                                         ++p;
1370                                         ec->handler_offset = read16 (p);
1371                                         p += 2;
1372                                         ec->handler_len = *p;
1373                                         ++p;
1374                                         ec->token_or_filter = read32 (p);
1375                                         p += 4;
1376                                 }
1377                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
1378                         }
1379
1380                 }
1381                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
1382                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
1383                 else
1384                         return;
1385         }
1386 }
1387
1388 MonoMethodHeader *
1389 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
1390 {
1391         MonoMethodHeader *mh;
1392         unsigned char flags = *(unsigned char *) ptr;
1393         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1394         guint16 fat_flags;
1395         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
1396         const unsigned char *code;
1397         int hsize;
1398         
1399         g_return_val_if_fail (ptr != NULL, NULL);
1400
1401         switch (format){
1402         case METHOD_HEADER_TINY_FORMAT:
1403                 mh = g_new0 (MonoMethodHeader, 1);
1404                 ptr++;
1405                 mh->max_stack = 8;
1406                 local_var_sig_tok = 0;
1407                 mh->code_size = flags >> 2;
1408                 mh->code = ptr;
1409                 return mh;
1410         case METHOD_HEADER_TINY_FORMAT1:
1411                 mh = g_new0 (MonoMethodHeader, 1);
1412                 ptr++;
1413                 mh->max_stack = 8;
1414                 local_var_sig_tok = 0;
1415
1416                 /*
1417                  * The spec claims 3 bits, but the Beta2 is
1418                  * incorrect
1419                  */
1420                 mh->code_size = flags >> 2;
1421                 mh->code = ptr;
1422                 return mh;
1423         case METHOD_HEADER_FAT_FORMAT:
1424                 fat_flags = read16 (ptr);
1425                 ptr += 2;
1426                 hsize = (fat_flags >> 12) & 0xf;
1427                 max_stack = read16 (ptr);
1428                 ptr += 2;
1429                 code_size = read32 (ptr);
1430                 ptr += 4;
1431                 local_var_sig_tok = read32 (ptr);
1432                 ptr += 4;
1433
1434                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1435                         init_locals = 1;
1436                 else
1437                         init_locals = 0;
1438
1439                 code = ptr;
1440
1441                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1442                         break;
1443
1444                 /*
1445                  * There are more sections
1446                  */
1447                 ptr = code + code_size;
1448                 
1449                 break;
1450                 
1451         default:
1452                 return NULL;
1453         }
1454                        
1455         if (local_var_sig_tok) {
1456                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
1457                 const char *ptr;
1458                 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
1459                 int len=0, i, bsize;
1460
1461                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
1462                 ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
1463                 bsize = mono_metadata_decode_blob_size (ptr, &ptr);
1464                 if (*ptr != 0x07)
1465                         g_warning ("wrong signature for locals blob");
1466                 ptr++;
1467                 len = mono_metadata_decode_value (ptr, &ptr);
1468                 mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1469                 mh->num_locals = len;
1470                 for (i = 0; i < len; ++i)
1471                         mh->locals [i] = mono_metadata_parse_type (m, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1472         } else {
1473                 mh = g_new0 (MonoMethodHeader, 1);
1474         }
1475         mh->code = code;
1476         mh->code_size = code_size;
1477         mh->max_stack = max_stack;
1478         mh->init_locals = init_locals;
1479         if (fat_flags & METHOD_HEADER_MORE_SECTS)
1480                 parse_section_data (mh, (const unsigned char*)ptr);
1481         return mh;
1482 }
1483
1484 void
1485 mono_metadata_free_mh (MonoMethodHeader *mh)
1486 {
1487         int i;
1488         for (i = 0; i < mh->num_locals; ++i)
1489                 mono_metadata_free_type (mh->locals[i]);
1490         g_free (mh->clauses);
1491         g_free (mh);
1492 }
1493
1494 /**
1495  * mono_metadata_parse_field_type:
1496  * @m: metadata context to extract information from
1497  * @ptr: pointer to the field signature
1498  *
1499  * Parses the field signature, and returns the type information for it. 
1500  *
1501  * Returns: The MonoType that was extracted from @ptr.
1502  */
1503 MonoType *
1504 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
1505 {
1506         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
1507 }
1508
1509 MonoType *
1510 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
1511 {
1512         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
1513 }
1514
1515 /*
1516  * mono_metadata_token_from_dor:
1517  * @dor_token: A TypeDefOrRef coded index
1518  *
1519  * dor_token is a TypeDefOrRef coded index: it contains either
1520  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
1521  * bits contain an index into the table.
1522  *
1523  * Returns: an expanded token
1524  */
1525 guint32
1526 mono_metadata_token_from_dor (guint32 dor_index)
1527 {
1528         guint32 table, idx;
1529
1530         table = dor_index & 0x03;
1531         idx = dor_index >> 2;
1532
1533         switch (table){
1534         case 0: /* TypeDef */
1535                 return MONO_TOKEN_TYPE_DEF | idx;
1536
1537         case 1: /* TypeRef */
1538                 return MONO_TOKEN_TYPE_REF | idx;
1539
1540         case 2: /* TypeSpec */
1541                 return MONO_TOKEN_TYPE_SPEC | idx;
1542
1543         default:
1544                 g_assert_not_reached ();
1545         }
1546
1547         return 0;
1548 }
1549
1550 /*
1551  * We use this to pass context information to the row locator
1552  */
1553 typedef struct {
1554         int idx;                        /* The index that we are trying to locate */
1555         int col_idx;            /* The index in the row where idx may be stored */
1556         MonoTableInfo *t;       /* pointer to the table */
1557         guint32 result;
1558 } locator_t;
1559
1560 #define CSIZE(x) (sizeof (x) / 4)
1561
1562 /*
1563  * How the row locator works.
1564  *
1565  *   Table A
1566  *   ___|___
1567  *   ___|___         Table B
1568  *   ___|___------>  _______
1569  *   ___|___         _______
1570  *   
1571  * A column in the rows of table A references an index in table B.
1572  * For example A may be the TYPEDEF table and B the METHODDEF table.
1573  * 
1574  * Given an index in table B we want to get the row in table A
1575  * where the column n references our index in B.
1576  *
1577  * In the locator_t structure:
1578  *      t is table A
1579  *      col_idx is the column number
1580  *      index is the index in table B
1581  *      result will be the index in table A
1582  *
1583  * Examples:
1584  * Table A              Table B         column (in table A)
1585  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
1586  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
1587  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
1588  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
1589  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
1590  *
1591  * Note that we still don't support encoded indexes.
1592  *
1593  */
1594 static int
1595 typedef_locator (const void *a, const void *b)
1596 {
1597         locator_t *loc = (locator_t *) a;
1598         char *bb = (char *) b;
1599         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
1600         guint32 col, col_next;
1601
1602         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
1603
1604         if (loc->idx < col)
1605                 return -1;
1606
1607         /*
1608          * Need to check that the next row is valid.
1609          */
1610         if (typedef_index + 1 < loc->t->rows) {
1611                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
1612                 if (loc->idx >= col_next)
1613                         return 1;
1614
1615                 if (col == col_next)
1616                         return 1; 
1617         }
1618
1619         loc->result = typedef_index;
1620         
1621         return 0;
1622 }
1623
1624 static int
1625 table_locator (const void *a, const void *b)
1626 {
1627         locator_t *loc = (locator_t *) a;
1628         char *bb = (char *) b;
1629         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
1630         guint32 col;
1631         
1632         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
1633
1634         if (loc->idx == col) {
1635                 loc->result = table_index;
1636                 return 0;
1637         }
1638         if (loc->idx < col)
1639                 return -1;
1640         else 
1641                 return 1;
1642 }
1643
1644 guint32
1645 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
1646 {
1647         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1648         locator_t loc;
1649
1650         if (!tdef->base)
1651                 return 0;
1652
1653         loc.idx = mono_metadata_token_index (index);
1654         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
1655         loc.t = tdef;
1656
1657         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1658                 g_assert_not_reached ();
1659
1660         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1661         return loc.result + 1;
1662 }
1663
1664 guint32
1665 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
1666 {
1667         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
1668         locator_t loc;
1669         
1670         if (!tdef->base)
1671                 return 0;
1672
1673         loc.idx = mono_metadata_token_index (index);
1674         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
1675         loc.t = tdef;
1676
1677         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1678                 g_assert_not_reached ();
1679
1680         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1681         return loc.result + 1;
1682 }
1683
1684 MonoClass**
1685 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
1686 {
1687         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
1688         locator_t loc;
1689         guint32 start, i;
1690         guint32 cols [MONO_INTERFACEIMPL_SIZE];
1691         MonoClass **result;
1692         
1693         *count = 0;
1694
1695         if (!tdef->base)
1696                 return NULL;
1697
1698         loc.idx = mono_metadata_token_index (index);
1699         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
1700         loc.t = tdef;
1701
1702         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
1703                 return NULL;
1704
1705         start = loc.result;
1706         /*
1707          * We may end up in the middle of the rows... 
1708          */
1709         while (start > 0) {
1710                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
1711                         start--;
1712                 else
1713                         break;
1714         }
1715         result = NULL;
1716         i = 0;
1717         while (start < tdef->rows) {
1718                 mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE);
1719                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
1720                         break;
1721                 result = g_renew (MonoClass*, result, i + 1);
1722                 result [i] = mono_class_get (meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]));
1723                 *count = ++i;
1724                 ++start;
1725         }
1726         return result;
1727 }
1728
1729 /*
1730  * Return the typedef token of the type index is defined into.
1731  * Return 0 if the index represents a toplevel type.
1732  */
1733 guint32
1734 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
1735 {
1736         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
1737         locator_t loc;
1738         
1739         if (!tdef->base)
1740                 return 0;
1741
1742         loc.idx = mono_metadata_token_index (index);
1743         loc.col_idx = MONO_NESTED_CLASS_NESTED;
1744         loc.t = tdef;
1745
1746         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
1747                 return 0;
1748
1749         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1750         return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
1751 }
1752
1753 guint32
1754 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index)
1755 {
1756         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
1757         locator_t loc;
1758         guint32 start;
1759         
1760         if (!tdef->base)
1761                 return 0;
1762
1763         loc.idx = mono_metadata_token_index (index);
1764         loc.col_idx = MONO_NESTED_CLASS_ENCLOSING;
1765         loc.t = tdef;
1766
1767         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
1768                 return 0;
1769
1770         start = loc.result;
1771
1772         while (start > 0) {
1773                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
1774                         start--;
1775                 else
1776                         break;
1777         }
1778
1779         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1780         return start + 1;
1781 }
1782
1783 /*
1784  * Return the info stored in the ClassLAyout table for the given typedef token.
1785  * Returns 0 if the info is not found.
1786  */
1787 guint32
1788 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
1789 {
1790         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
1791         locator_t loc;
1792         guint32 cols [MONO_CLASS_LAYOUT_SIZE];
1793         
1794         if (!tdef->base)
1795                 return 0;
1796
1797         loc.idx = mono_metadata_token_index (index);
1798         loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
1799         loc.t = tdef;
1800
1801         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
1802                 return 0;
1803
1804         mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
1805         if (packing)
1806                 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
1807         if (size)
1808                 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
1809
1810         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1811         return loc.result + 1;
1812 }
1813
1814 #ifndef __GNUC__
1815 #define __alignof__(a) sizeof(a)
1816 #endif
1817
1818 /*
1819  * mono_type_size:
1820  * @t: the type to return the size of
1821  *
1822  * Returns: the number of bytes required to hold an instance of this
1823  * type in memory
1824  */
1825 int
1826 mono_type_size (MonoType *t, gint *align)
1827 {
1828         if (!t) {
1829                 *align = 1;
1830                 return 0;
1831         }
1832         if (t->byref) {
1833                 *align = __alignof__(gpointer);
1834                 return sizeof (gpointer);
1835         }
1836
1837         switch (t->type){
1838         case MONO_TYPE_VOID:
1839                 *align = 1;
1840                 return 0;
1841         case MONO_TYPE_BOOLEAN:
1842                 *align = __alignof__(char);
1843                 return sizeof (char);
1844                 
1845         case MONO_TYPE_CHAR:
1846                 *align = __alignof__(short);
1847                 return sizeof (short);
1848                 
1849         case MONO_TYPE_I1:
1850         case MONO_TYPE_U1:
1851                 *align = __alignof__(char);
1852                 return 1;
1853                 
1854         case MONO_TYPE_I2:
1855         case MONO_TYPE_U2:
1856                 *align = __alignof__(gint16);
1857                 return 2;
1858                 
1859         case MONO_TYPE_I4:
1860         case MONO_TYPE_U4:
1861                 *align = __alignof__(gint32);
1862                 return 4;
1863         case MONO_TYPE_R4:
1864                 *align = __alignof__(float);
1865                 return 4;
1866                 
1867         case MONO_TYPE_I8:
1868         case MONO_TYPE_U8:
1869                 *align = __alignof__(gint64);
1870         case MONO_TYPE_R8:
1871                 *align = __alignof__(double);
1872                 return 8;
1873                 
1874         case MONO_TYPE_I:
1875         case MONO_TYPE_U:
1876                 *align = __alignof__(gpointer);
1877                 return sizeof (gpointer);
1878                 
1879         case MONO_TYPE_STRING:
1880                 *align = __alignof__(gpointer);
1881                 return sizeof (gpointer);
1882                 
1883         case MONO_TYPE_OBJECT:
1884                 *align = __alignof__(gpointer);
1885                 return sizeof (gpointer);
1886                 
1887         case MONO_TYPE_VALUETYPE: {
1888                 guint32 size;
1889
1890                 if (t->data.klass->enumtype) {
1891                         return mono_type_size (t->data.klass->enum_basetype, align);
1892                 } else {
1893                         size = mono_class_value_size (t->data.klass, align);
1894                         return size;
1895                 }
1896         }
1897         case MONO_TYPE_CLASS:
1898         case MONO_TYPE_SZARRAY:
1899         case MONO_TYPE_PTR:
1900         case MONO_TYPE_FNPTR:
1901         case MONO_TYPE_ARRAY:
1902         case MONO_TYPE_TYPEDBYREF: /* we may want to use a struct {MonoType* type, void *data } instead ...*/
1903                 *align = __alignof__(gpointer);
1904                 return sizeof (gpointer);
1905         default:
1906                 g_error ("type 0x%02x unknown", t->type);
1907         }
1908         return 0;
1909 }
1910
1911 /*
1912  * mono_type_stack_size:
1913  * @t: the type to return the size it uses on the stack
1914  *
1915  * Returns: the number of bytes required to hold an instance of this
1916  * type on the runtime stack
1917  */
1918 int
1919 mono_type_stack_size (MonoType *t, gint *align)
1920 {
1921         g_assert (t != NULL);
1922
1923         if (t->byref) {
1924                 *align = __alignof__(gpointer);
1925                 return sizeof (gpointer);
1926         }
1927
1928         switch (t->type){
1929         case MONO_TYPE_BOOLEAN:
1930         case MONO_TYPE_CHAR:
1931         case MONO_TYPE_I1:
1932         case MONO_TYPE_U1:
1933         case MONO_TYPE_I2:
1934         case MONO_TYPE_U2:
1935         case MONO_TYPE_I4:
1936         case MONO_TYPE_U4:
1937         case MONO_TYPE_I:
1938         case MONO_TYPE_U:
1939         case MONO_TYPE_STRING:
1940         case MONO_TYPE_OBJECT:
1941         case MONO_TYPE_CLASS:
1942         case MONO_TYPE_SZARRAY:
1943         case MONO_TYPE_PTR:
1944         case MONO_TYPE_FNPTR:
1945         case MONO_TYPE_ARRAY:
1946         case MONO_TYPE_TYPEDBYREF:
1947                 *align = __alignof__(gpointer);
1948                 return sizeof (gpointer);
1949         case MONO_TYPE_R4:
1950                 *align = __alignof__(float);
1951                 return 4;
1952                 
1953         case MONO_TYPE_I8:
1954         case MONO_TYPE_U8:
1955                 *align = __alignof__(gint64);
1956         case MONO_TYPE_R8:
1957                 *align = __alignof__(double);
1958                 return 8;
1959                 
1960         case MONO_TYPE_VALUETYPE: {
1961                 guint32 size;
1962
1963                 if (t->data.klass->enumtype)
1964                         return mono_type_stack_size (t->data.klass->enum_basetype, align);
1965                 else {
1966                         size = mono_class_value_size (t->data.klass, align);
1967                         *align = __alignof__(gpointer);
1968                         return size;
1969                 }
1970         }
1971         default:
1972                 g_error ("type 0x%02x unknown", t->type);
1973         }
1974         return 0;
1975 }
1976
1977 gboolean
1978 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
1979 {
1980         if (t1->type != t2->type ||
1981             t1->byref != t2->byref)
1982                 return FALSE;
1983
1984         switch (t1->type) {
1985         case MONO_TYPE_VOID:
1986         case MONO_TYPE_BOOLEAN:
1987         case MONO_TYPE_CHAR:
1988         case MONO_TYPE_I1:
1989         case MONO_TYPE_U1:
1990         case MONO_TYPE_I2:
1991         case MONO_TYPE_U2:
1992         case MONO_TYPE_I4:
1993         case MONO_TYPE_U4:
1994         case MONO_TYPE_I8:
1995         case MONO_TYPE_U8:
1996         case MONO_TYPE_R4:
1997         case MONO_TYPE_R8:
1998         case MONO_TYPE_STRING:
1999         case MONO_TYPE_I:
2000         case MONO_TYPE_U:
2001         case MONO_TYPE_OBJECT:
2002                 return TRUE;
2003         case MONO_TYPE_VALUETYPE:
2004         case MONO_TYPE_CLASS:
2005                 return t1->data.klass == t2->data.klass;
2006         case MONO_TYPE_SZARRAY:
2007                 return mono_metadata_type_equal (t1->data.type, t2->data.type);
2008         default:
2009                 g_error ("implement type compare for %0x!", t1->type);
2010                 return FALSE;
2011         }
2012
2013         return FALSE;
2014 }
2015
2016 gboolean
2017 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
2018 {
2019         int i;
2020
2021         if (sig1->hasthis != sig2->hasthis ||
2022             sig1->param_count != sig2->param_count)
2023                 return FALSE;
2024
2025         for (i = 0; i < sig1->param_count; i++) { 
2026                 MonoType *p1 = sig1->params[i];
2027                 MonoType *p2 = sig2->params[i];
2028                 
2029                 if (p1->attrs != p2->attrs)
2030                         return FALSE;
2031                 
2032                 if (!mono_metadata_type_equal (p1, p2))
2033                         return FALSE;
2034         }
2035
2036         return TRUE;
2037 }
2038
2039 void
2040 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
2041 {
2042         char *p = buf;
2043         
2044         if (value <= 127)
2045                 *p++ = value;
2046         else if (value <= 16384) {
2047                 p [0] = 0x80 | (value >> 8);
2048                 p [1] = value & 0xff;
2049                 p += 2;
2050         } else {
2051                 p [0] = (value >> 24) | 0xc0;
2052                 p [1] = (value >> 16) & 0xff;
2053                 p [2] = (value >> 8) & 0xff;
2054                 p [3] = value & 0xff;
2055                 p += 4;
2056         }
2057         if (endbuf)
2058                 *endbuf = p;
2059 }
2060
2061 /*
2062  * mono_metadata_field_info:
2063  * @meta: the Image the field is defined in
2064  * @index: the index in the field table representing the field
2065  * @offset: a pointer to an integer where to store the offset that 
2066  * may have been specified for the field in a FieldLayout table
2067  * @rva: a pointer to the address of the field data in the image that
2068  * may have been defined in a FieldRVA table
2069  * @marshal_info: a pointer to the marshal signature that may have been 
2070  * defined for the field in a FieldMarshal table.
2071  *
2072  * Gather info for field @index that may have been defined in the FieldLayout, 
2073  * FieldRVA and FieldMarshal tables.
2074  * Either of offset, rva and marshal_info can be NULL if you're not interested 
2075  * in the data.
2076  */
2077 void
2078 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, const char **rva, const char **marshal_info)
2079 {
2080         MonoTableInfo *tdef;
2081         locator_t loc;
2082
2083         loc.idx = index + 1;
2084         if (offset) {
2085                 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
2086
2087                 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
2088                 loc.t = tdef;
2089
2090                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
2091                         *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
2092                 } else {
2093                         *offset = (guint32)-1;
2094                 }
2095         }
2096         if (rva) {
2097                 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
2098
2099                 loc.col_idx = MONO_FIELD_RVA_FIELD;
2100                 loc.t = tdef;
2101
2102                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
2103                         /*
2104                          * LAMESPEC: There is no signature, no nothing, just the raw data.
2105                          */
2106                         *rva = mono_cli_rva_map (meta->image_info, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA));
2107                 } else {
2108                         *rva = NULL;
2109                 }
2110         }
2111
2112 }
2113
2114 /*
2115  * mono_metadata_get_constant_index:
2116  * @meta: the Image the field is defined in
2117  * @index: the token that may have a row defined in the constants table
2118  *
2119  * @token must be a FieldDef, ParamDef or PropertyDef token.
2120  *
2121  * Returns: the index into the Constsnts table or 0 if not found.
2122  */
2123 guint32
2124 mono_metadata_get_constant_index (MonoImage *meta, guint32 token)
2125 {
2126         MonoTableInfo *tdef;
2127         locator_t loc;
2128         guint32 index = mono_metadata_token_index (token);
2129
2130         tdef = &meta->tables [MONO_TABLE_CONSTANT];
2131         index <<= HASCONSTANT_BITS;
2132         switch (mono_metadata_token_table (token)) {
2133         case MONO_TABLE_FIELD:
2134                 index |= HASCONSTANT_FIEDDEF;
2135                 break;
2136         case MONO_TABLE_PARAM:
2137                 index |= HASCONSTANT_PARAM;
2138                 break;
2139         case MONO_TABLE_PROPERTY:
2140                 index |= HASCONSTANT_PROPERTY;
2141                 break;
2142         default:
2143                 g_warning ("Not a valid token for the constant table: 0x%08x", token);
2144                 return 0;
2145         }
2146         loc.idx = index;
2147         loc.col_idx = MONO_CONSTANT_PARENT;
2148         loc.t = tdef;
2149
2150         if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
2151                 return loc.result + 1;
2152         }
2153         return 0;
2154 }
2155
2156 guint32
2157 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
2158 {
2159         locator_t loc;
2160         guint32 start, end;
2161         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_PROPERTYMAP];
2162
2163         *end_idx = 0;
2164         
2165         if (!tdef->base)
2166                 return 0;
2167
2168         loc.t = tdef;
2169         loc.col_idx = MONO_PROPERTY_MAP_PARENT;
2170         loc.idx = index + 1;
2171
2172         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2173                 return 0;
2174         
2175         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
2176         if (loc.result + 1 < tdef->rows) {
2177                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
2178         } else {
2179                 end = meta->tables [MONO_TABLE_PROPERTY].rows;
2180         }
2181
2182         *end_idx = end;
2183         return start - 1;
2184 }
2185
2186 guint32
2187 mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *end_idx)
2188 {
2189         locator_t loc;
2190         guint start, end;
2191         guint32 cols [MONO_METHOD_SEMA_SIZE];
2192         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
2193
2194         *end_idx = 0;
2195         if (!msemt->base)
2196                 return 0;
2197
2198         loc.t = msemt;
2199         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
2200         loc.idx = ((index + 1) << 1) | 1; /* Method association coded index */
2201
2202         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
2203                 return 0;
2204
2205         start = loc.result;
2206         /*
2207          * We may end up in the middle of the rows... 
2208          */
2209         while (start > 0) {
2210                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
2211                         start--;
2212                 else
2213                         break;
2214         }
2215         end = start + 1;
2216         while (end < msemt->rows) {
2217                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
2218                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
2219                         break;
2220                 ++end;
2221         }
2222         *end_idx = end;
2223         return start;
2224 }
2225
2226 /**
2227  * @image: context where the image is created
2228  * @type_spec:  typespec token
2229  */
2230 MonoType *
2231 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
2232 {
2233         guint32 idx = mono_metadata_token_index (type_spec);
2234         MonoTableInfo *t;
2235         guint32 cols [MONO_TYPESPEC_SIZE];       
2236         const char *ptr;
2237         guint32 len;
2238         MonoType *type;
2239
2240         t = &image->tables [MONO_TABLE_TYPESPEC];
2241         
2242         mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
2243         ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
2244         len = mono_metadata_decode_value (ptr, &ptr);
2245         type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
2246
2247         return type;
2248 }
2249