reapply
[mono.git] / mono / metadata / metadata.c
1 /*
2  * metadata.c: Routines for accessing the metadata
3  *
4  * Authors:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001-2002 Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <glib.h>
16 #include "metadata.h"
17 #include "tabledefs.h"
18 #include "mono-endian.h"
19 #include "cil-coff.h"
20 #include "tokentype.h"
21 #include "metadata-internals.h"
22 #include "class-internals.h"
23 #include "class.h"
24
25 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
26                                          const char *ptr, const char **rptr);
27
28 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
29 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
30 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
31 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
32                                                     gboolean signature_only);
33
34 /*
35  * This enumeration is used to describe the data types in the metadata
36  * tables
37  */
38 enum {
39         MONO_MT_END,
40
41         /* Sized elements */
42         MONO_MT_UINT32,
43         MONO_MT_UINT16,
44         MONO_MT_UINT8,
45
46         /* Index into Blob heap */
47         MONO_MT_BLOB_IDX,
48
49         /* Index into String heap */
50         MONO_MT_STRING_IDX,
51
52         /* GUID index */
53         MONO_MT_GUID_IDX,
54
55         /* Pointer into a table */
56         MONO_MT_TABLE_IDX,
57
58         /* HasConstant:Parent pointer (Param, Field or Property) */
59         MONO_MT_CONST_IDX,
60
61         /* HasCustomAttribute index.  Indexes any table except CustomAttribute */
62         MONO_MT_HASCAT_IDX,
63         
64         /* CustomAttributeType encoded index */
65         MONO_MT_CAT_IDX,
66
67         /* HasDeclSecurity index: TypeDef Method or Assembly */
68         MONO_MT_HASDEC_IDX,
69
70         /* Implementation coded index: File, Export AssemblyRef */
71         MONO_MT_IMPL_IDX,
72
73         /* HasFieldMarshal coded index: Field or Param table */
74         MONO_MT_HFM_IDX,
75
76         /* MemberForwardedIndex: Field or Method */
77         MONO_MT_MF_IDX,
78
79         /* TypeDefOrRef coded index: typedef, typeref, typespec */
80         MONO_MT_TDOR_IDX,
81
82         /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
83         MONO_MT_MRP_IDX,
84
85         /* MethodDefOrRef coded index: Method or Member Ref table */
86         MONO_MT_MDOR_IDX,
87
88         /* HasSemantic coded index: Event or Property */
89         MONO_MT_HS_IDX,
90
91         /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
92         MONO_MT_RS_IDX
93 };
94
95 const static unsigned char TableSchemas [] = {
96 #define ASSEMBLY_SCHEMA_OFFSET 0
97         MONO_MT_UINT32,     /* "HashId" }, */
98         MONO_MT_UINT16,     /* "Major" },  */
99         MONO_MT_UINT16,     /* "Minor" }, */
100         MONO_MT_UINT16,     /* "BuildNumber" }, */
101         MONO_MT_UINT16,     /* "RevisionNumber" }, */
102         MONO_MT_UINT32,     /* "Flags" }, */
103         MONO_MT_BLOB_IDX,   /* "PublicKey" }, */
104         MONO_MT_STRING_IDX, /* "Name" }, */
105         MONO_MT_STRING_IDX, /* "Culture" }, */
106         MONO_MT_END,
107
108 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
109         MONO_MT_UINT32,     /* "OSPlatformID" }, */
110         MONO_MT_UINT32,     /* "OSMajor" }, */
111         MONO_MT_UINT32,     /* "OSMinor" }, */
112         MONO_MT_END,
113
114 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
115         MONO_MT_UINT32,     /* "Processor" }, */
116         MONO_MT_END,
117
118 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
119         MONO_MT_UINT16,     /* "Major" }, */
120         MONO_MT_UINT16,     /* "Minor" }, */
121         MONO_MT_UINT16,     /* "Build" }, */
122         MONO_MT_UINT16,     /* "Revision" }, */
123         MONO_MT_UINT32,     /* "Flags" }, */
124         MONO_MT_BLOB_IDX,   /* "PublicKeyOrToken" }, */
125         MONO_MT_STRING_IDX, /* "Name" }, */
126         MONO_MT_STRING_IDX, /* "Culture" }, */
127         MONO_MT_BLOB_IDX,   /* "HashValue" }, */
128         MONO_MT_END,
129
130 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
131         MONO_MT_UINT32,     /* "OSPlatformID" }, */
132         MONO_MT_UINT32,     /* "OSMajorVersion" }, */
133         MONO_MT_UINT32,     /* "OSMinorVersion" }, */
134         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
135         MONO_MT_END,
136
137 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
138         MONO_MT_UINT32,     /* "Processor" }, */
139         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
140         MONO_MT_END,
141
142 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
143         MONO_MT_UINT16,     /* "PackingSize" }, */
144         MONO_MT_UINT32,     /* "ClassSize" }, */
145         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
146         MONO_MT_END,
147
148 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
149         MONO_MT_UINT8,      /* "Type" }, */
150         MONO_MT_UINT8,      /* "PaddingZero" }, */
151         MONO_MT_CONST_IDX,  /* "Parent" }, */
152         MONO_MT_BLOB_IDX,   /* "Value" }, */
153         MONO_MT_END,
154
155 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
156         MONO_MT_HASCAT_IDX, /* "Parent" }, */
157         MONO_MT_CAT_IDX,    /* "Type" }, */
158         MONO_MT_BLOB_IDX,   /* "Value" }, */
159         MONO_MT_END,
160
161 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
162         MONO_MT_UINT16,     /* "Action" }, */
163         MONO_MT_HASDEC_IDX, /* "Parent" }, */
164         MONO_MT_BLOB_IDX,   /* "PermissionSet" }, */
165         MONO_MT_END,
166
167 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
168         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
169         MONO_MT_TABLE_IDX,  /* "EventList:Event" }, */
170         MONO_MT_END,
171
172 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
173         MONO_MT_UINT16,     /* "EventFlags#EventAttribute" }, */
174         MONO_MT_STRING_IDX, /* "Name" }, */
175         MONO_MT_TABLE_IDX,  /* "EventType" }, TypeDef or TypeRef  */
176         MONO_MT_END,
177
178 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
179         MONO_MT_UINT32,     /* "Flags" }, */
180         MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
181         MONO_MT_STRING_IDX, /* "TypeName" }, */
182         MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
183         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
184         MONO_MT_END,
185
186 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
187         MONO_MT_UINT16,     /* "Flags" }, */
188         MONO_MT_STRING_IDX, /* "Name" }, */
189         MONO_MT_BLOB_IDX,   /* "Signature" }, */
190         MONO_MT_END,
191
192 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
193         MONO_MT_UINT32,     /* "Offset" }, */
194         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
195         MONO_MT_END,
196
197 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
198         MONO_MT_HFM_IDX,    /* "Parent" }, */
199         MONO_MT_BLOB_IDX,   /* "NativeType" }, */
200         MONO_MT_END,
201
202 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
203         MONO_MT_UINT32,     /* "RVA" }, */
204         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
205         MONO_MT_END,
206
207 #define FILE_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
208         MONO_MT_UINT32,     /* "Flags" }, */
209         MONO_MT_STRING_IDX, /* "Name" }, */
210         MONO_MT_BLOB_IDX,   /* "Value" },  */
211         MONO_MT_END,
212
213 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
214         MONO_MT_UINT16,     /* "MappingFlag" }, */
215         MONO_MT_MF_IDX,     /* "MemberForwarded" }, */
216         MONO_MT_STRING_IDX, /* "ImportName" }, */
217         MONO_MT_TABLE_IDX,  /* "ImportScope:ModuleRef" }, */
218         MONO_MT_END,
219
220 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
221         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" },  */
222         MONO_MT_TDOR_IDX,  /* "Interface=TypeDefOrRef" }, */
223         MONO_MT_END,
224
225 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
226         MONO_MT_UINT32,     /* "Offset" }, */
227         MONO_MT_UINT32,     /* "Flags" }, */
228         MONO_MT_STRING_IDX, /* "Name" }, */
229         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
230         MONO_MT_END,
231
232 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
233         MONO_MT_MRP_IDX,    /* "Class" }, */
234         MONO_MT_STRING_IDX, /* "Name" }, */
235         MONO_MT_BLOB_IDX,   /* "Signature" }, */
236         MONO_MT_END,
237
238 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
239         MONO_MT_UINT32,     /* "RVA" }, */
240         MONO_MT_UINT16,     /* "ImplFlags#MethodImplAttributes" }, */
241         MONO_MT_UINT16,     /* "Flags#MethodAttribute" }, */
242         MONO_MT_STRING_IDX, /* "Name" }, */
243         MONO_MT_BLOB_IDX,   /* "Signature" }, */
244         MONO_MT_TABLE_IDX,  /* "ParamList:Param" }, */
245         MONO_MT_END,
246
247 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
248         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" }, */
249         MONO_MT_MDOR_IDX,   /* "MethodBody" }, */
250         MONO_MT_MDOR_IDX,   /* "MethodDeclaration" }, */
251         MONO_MT_END,
252
253 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
254         MONO_MT_UINT16,     /* "MethodSemantic" }, */
255         MONO_MT_TABLE_IDX,  /* "Method:Method" }, */
256         MONO_MT_HS_IDX,     /* "Association" }, */
257         MONO_MT_END,
258
259 #define MODULE_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
260         MONO_MT_UINT16,     /* "Generation" }, */
261         MONO_MT_STRING_IDX, /* "Name" }, */
262         MONO_MT_GUID_IDX,   /* "MVID" }, */
263         MONO_MT_GUID_IDX,   /* "EncID" }, */
264         MONO_MT_GUID_IDX,   /* "EncBaseID" }, */
265         MONO_MT_END,
266
267 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
268         MONO_MT_STRING_IDX, /* "Name" }, */
269         MONO_MT_END,
270
271 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
272         MONO_MT_TABLE_IDX,  /* "NestedClass:TypeDef" }, */
273         MONO_MT_TABLE_IDX,  /* "EnclosingClass:TypeDef" }, */
274         MONO_MT_END,
275
276 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
277         MONO_MT_UINT16,     /* "Flags" }, */
278         MONO_MT_UINT16,     /* "Sequence" }, */
279         MONO_MT_STRING_IDX, /* "Name" }, */
280         MONO_MT_END,
281
282 #define PROPERTY_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
283         MONO_MT_UINT16,     /* "Flags" }, */
284         MONO_MT_STRING_IDX, /* "Name" }, */
285         MONO_MT_BLOB_IDX,   /* "Type" }, */
286         MONO_MT_END,
287
288 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
289         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
290         MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
291         MONO_MT_END,
292
293 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
294         MONO_MT_BLOB_IDX,   /* "Signature" }, */
295         MONO_MT_END,
296
297 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
298         MONO_MT_UINT32,     /* "Flags" }, */
299         MONO_MT_STRING_IDX, /* "Name" }, */
300         MONO_MT_STRING_IDX, /* "Namespace" }, */
301         MONO_MT_TDOR_IDX,   /* "Extends" }, */
302         MONO_MT_TABLE_IDX,  /* "FieldList:Field" }, */
303         MONO_MT_TABLE_IDX,  /* "MethodList:Method" }, */
304         MONO_MT_END,
305
306 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
307         MONO_MT_RS_IDX,     /* "ResolutionScope=ResolutionScope" }, */
308         MONO_MT_STRING_IDX, /* "Name" }, */
309         MONO_MT_STRING_IDX, /* "Namespace" }, */
310         MONO_MT_END,
311
312 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
313         MONO_MT_BLOB_IDX,   /* "Signature" }, */
314         MONO_MT_END,
315
316 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
317         MONO_MT_UINT16,     /* "Number" }, */
318         MONO_MT_UINT16,     /* "Flags" }, */
319         MONO_MT_TABLE_IDX,  /* "Owner" },  TypeDef or MethodDef */
320         MONO_MT_STRING_IDX, /* "Name" }, */
321         MONO_MT_END,
322
323 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
324         MONO_MT_MDOR_IDX,   /* "Method" }, */
325         MONO_MT_BLOB_IDX,   /* "Signature" }, */
326         MONO_MT_END,
327
328 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
329         MONO_MT_TABLE_IDX,  /* "GenericParam" }, */
330         MONO_MT_TDOR_IDX,   /* "Constraint" }, */
331         MONO_MT_END,
332
333 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
334         MONO_MT_END
335 };
336
337 /* Must be the same order as MONO_TABLE_* */
338 const static unsigned char
339 table_description [] = {
340         MODULE_SCHEMA_OFFSET,
341         TYPEREF_SCHEMA_OFFSET,
342         TYPEDEF_SCHEMA_OFFSET,
343         NULL_SCHEMA_OFFSET,
344         FIELD_SCHEMA_OFFSET,
345         NULL_SCHEMA_OFFSET,
346         METHOD_SCHEMA_OFFSET,
347         NULL_SCHEMA_OFFSET,
348         PARAM_SCHEMA_OFFSET,
349         IFACEMAP_SCHEMA_OFFSET,
350         MEMBERREF_SCHEMA_OFFSET, /* 0xa */
351         CONSTANT_SCHEMA_OFFSET,
352         CUSTOM_ATTR_SCHEMA_OFFSET,
353         FIELD_MARSHAL_SCHEMA_OFFSET,
354         DECL_SEC_SCHEMA_OFFSET,
355         CLASS_LAYOUT_SCHEMA_OFFSET,
356         FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
357         STDALON_SIG_SCHEMA_OFFSET,
358         EVENTMAP_SCHEMA_OFFSET,
359         NULL_SCHEMA_OFFSET,
360         EVENT_SCHEMA_OFFSET,
361         PROPERTY_MAP_SCHEMA_OFFSET,
362         NULL_SCHEMA_OFFSET,
363         PROPERTY_SCHEMA_OFFSET,
364         METHOD_SEMA_SCHEMA_OFFSET,
365         METHOD_IMPL_SCHEMA_OFFSET,
366         MODULEREF_SCHEMA_OFFSET, /* 0x1a */
367         TYPESPEC_SCHEMA_OFFSET,
368         IMPLMAP_SCHEMA_OFFSET,
369         FIELD_RVA_SCHEMA_OFFSET,
370         NULL_SCHEMA_OFFSET,
371         NULL_SCHEMA_OFFSET,
372         ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
373         ASSEMBLYPROC_SCHEMA_OFFSET,
374         ASSEMBLYOS_SCHEMA_OFFSET,
375         ASSEMBLYREF_SCHEMA_OFFSET,
376         ASSEMBLYREFPROC_SCHEMA_OFFSET,
377         ASSEMBLYREFOS_SCHEMA_OFFSET,
378         FILE_SCHEMA_OFFSET,
379         EXPORTED_TYPE_SCHEMA_OFFSET,
380         MANIFEST_SCHEMA_OFFSET,
381         NESTED_CLASS_SCHEMA_OFFSET,
382         GENPARAM_SCHEMA_OFFSET, /* 0x2a */
383         METHOD_SPEC_SCHEMA_OFFSET,
384         GEN_CONSTRAINT_SCHEMA_OFFSET
385 };
386
387 #ifdef HAVE_ARRAY_ELEM_INIT
388 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
389 #define MSGSTRFIELD1(line) str##line
390 static const struct msgstr_t {
391 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
392 #include "mono/cil/tables.def"
393 #undef TABLEDEF
394 } tablestr = {
395 #define TABLEDEF(a,b) b,
396 #include "mono/cil/tables.def"
397 #undef TABLEDEF
398 };
399 static const gint16 tableidx [] = {
400 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
401 #include "mono/cil/tables.def"
402 #undef TABLEDEF
403 };
404
405 #else
406 #define TABLEDEF(a,b) b,
407 static const char* const
408 mono_tables_names [] = {
409 #include "mono/cil/tables.def"
410         NULL
411 };
412
413 #endif
414
415 /**
416  * mono_meta_table_name:
417  * @table: table index
418  *
419  * Returns: the name for the @table index
420  */
421 const char *
422 mono_meta_table_name (int table)
423 {
424         if ((table < 0) || (table > MONO_TABLE_LAST))
425                 return "";
426
427 #ifdef HAVE_ARRAY_ELEM_INIT
428         return (const char*)&tablestr + tableidx [table];
429 #else
430         return mono_tables_names [table];
431 #endif
432 }
433
434 /* The guy who wrote the spec for this should not be allowed near a
435  * computer again.
436  
437 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
438 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
439 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
440 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
441 inverse of this mapping.
442
443  */
444 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
445 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
446
447 /* Reference: Partition II - 23.2.6 */
448 /*
449  * mono_metadata_compute_size:
450  * @meta: metadata context
451  * @tableindex: metadata table number
452  * @result_bitfield: pointer to guint32 where to store additional info
453  * 
454  * mono_metadata_compute_size() computes the lenght in bytes of a single
455  * row in a metadata table. The size of each column is encoded in the
456  * @result_bitfield return value along with the number of columns in the table.
457  * the resulting bitfield should be handed to the mono_metadata_table_size()
458  * and mono_metadata_table_count() macros.
459  * This is a Mono runtime internal only function.
460  */
461 int
462 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
463 {
464         guint32 bitfield = 0;
465         int size = 0, field_size = 0;
466         int i, n, code;
467         int shift = 0;
468         const unsigned char *description = TableSchemas + table_description [tableindex];
469
470         for (i = 0; (code = description [i]) != MONO_MT_END; i++){
471                 switch (code){
472                 case MONO_MT_UINT32:
473                         field_size = 4; break;
474                         
475                 case MONO_MT_UINT16:
476                         field_size = 2; break;
477                         
478                 case MONO_MT_UINT8:
479                         field_size = 1; break;
480                         
481                 case MONO_MT_BLOB_IDX:
482                         field_size = meta->idx_blob_wide ? 4 : 2; break;
483                         
484                 case MONO_MT_STRING_IDX:
485                         field_size = meta->idx_string_wide ? 4 : 2; break;
486                         
487                 case MONO_MT_GUID_IDX:
488                         field_size = meta->idx_guid_wide ? 4 : 2; break;
489
490                 case MONO_MT_TABLE_IDX:
491                         /* Uhm, a table index can point to other tables besides the current one
492                          * so, it's not correct to use the rowcount of the current table to
493                          * get the size for this column - lupus 
494                          */
495                         switch (tableindex) {
496                         case MONO_TABLE_ASSEMBLYREFOS:
497                                 g_assert (i == 3);
498                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
499                         case MONO_TABLE_ASSEMBLYPROCESSOR:
500                                 g_assert (i == 1);
501                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
502                         case MONO_TABLE_CLASSLAYOUT:
503                                 g_assert (i == 2);
504                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
505                         case MONO_TABLE_EVENTMAP:
506                                 g_assert (i == 0 || i == 1);
507                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
508                                         idx_size(MONO_TABLE_TYPEDEF); 
509                                 break;
510                         case MONO_TABLE_EVENT:
511                                 g_assert (i == 2);
512                                 field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
513                                 field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
514                                 break;
515                         case MONO_TABLE_EXPORTEDTYPE:
516                                 g_assert (i == 1);
517                                 /* the index is in another metadata file, so it must be 4 */
518                                 field_size = 4; break;
519                         case MONO_TABLE_FIELDLAYOUT:
520                                 g_assert (i == 1);
521                                 field_size = idx_size (MONO_TABLE_FIELD); break;
522                         case MONO_TABLE_FIELDRVA:
523                                 g_assert (i == 1);
524                                 field_size = idx_size (MONO_TABLE_FIELD); break;
525                         case MONO_TABLE_IMPLMAP:
526                                 g_assert (i == 3);
527                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
528                         case MONO_TABLE_INTERFACEIMPL:
529                                 g_assert (i == 0);
530                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
531                         case MONO_TABLE_METHOD:
532                                 g_assert (i == 5);
533                                 field_size = idx_size (MONO_TABLE_PARAM); break;
534                         case MONO_TABLE_METHODIMPL:
535                                 g_assert (i == 0);
536                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
537                         case MONO_TABLE_METHODSEMANTICS:
538                                 g_assert (i == 1);
539                                 field_size = idx_size (MONO_TABLE_METHOD); break;
540                         case MONO_TABLE_NESTEDCLASS:
541                                 g_assert (i == 0 || i == 1);
542                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
543                         case MONO_TABLE_PROPERTYMAP:
544                                 g_assert (i == 0 || i == 1);
545                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
546                                         idx_size(MONO_TABLE_TYPEDEF); 
547                                 break;
548                         case MONO_TABLE_TYPEDEF:
549                                 g_assert (i == 4 || i == 5);
550                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
551                                         idx_size(MONO_TABLE_METHOD);
552                                 break;
553                         case MONO_TABLE_GENERICPARAM:
554                                 g_assert (i == 2 || i == 4 || i == 5);
555                                 if (i == 2)
556                                         field_size = MAX (idx_size (MONO_TABLE_METHOD), idx_size (MONO_TABLE_TYPEDEF));
557                                 else if (i == 4)
558                                         field_size = idx_size (MONO_TABLE_TYPEDEF);
559                                 else if (i == 5)
560                                         field_size = idx_size (MONO_TABLE_TYPEDEF);
561                                 break;
562
563                         case MONO_TABLE_GENERICPARAMCONSTRAINT:
564                                 g_assert (i == 0);
565                                 field_size = idx_size (MONO_TABLE_GENERICPARAM);
566                                 break;
567                                 
568                         default:
569                                 g_assert_not_reached ();
570                         }
571                         break;
572
573                         /*
574                          * HasConstant: ParamDef, FieldDef, Property
575                          */
576                 case MONO_MT_CONST_IDX:
577                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
578                                  meta->tables [MONO_TABLE_FIELD].rows);
579                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
580
581                         /* 2 bits to encode tag */
582                         field_size = rtsize (n, 16-2);
583                         break;
584
585                         /*
586                          * HasCustomAttribute: points to any table but
587                          * itself.
588                          */
589                 case MONO_MT_HASCAT_IDX:
590                         /*
591                          * We believe that since the signature and
592                          * permission are indexing the Blob heap,
593                          * we should consider the blob size first
594                          */
595                         /* I'm not a believer - lupus
596                         if (meta->idx_blob_wide){
597                                 field_size = 4;
598                                 break;
599                         }*/
600                         
601                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
602                                  meta->tables [MONO_TABLE_FIELD].rows);
603                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
604                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
605                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
606                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
607                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
608                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
609                         n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
610                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
611                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
612                         n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
613                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
614                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
615                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
616                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
617                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
618                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
619                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
620
621                         /* 5 bits to encode */
622                         field_size = rtsize (n, 16-5);
623                         break;
624
625                         /*
626                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
627                          * MemberRef and String.  
628                          */
629                 case MONO_MT_CAT_IDX:
630                         /* String is a heap, if it is wide, we know the size */
631                         /* See above, nope. 
632                         if (meta->idx_string_wide){
633                                 field_size = 4;
634                                 break;
635                         }*/
636                         
637                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
638                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
639                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
640                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
641
642                         /* 3 bits to encode */
643                         field_size = rtsize (n, 16-3);
644                         break;
645
646                         /*
647                          * HasDeclSecurity: Typedef, MethodDef, Assembly
648                          */
649                 case MONO_MT_HASDEC_IDX:
650                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
651                                  meta->tables [MONO_TABLE_METHOD].rows);
652                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
653
654                         /* 2 bits to encode */
655                         field_size = rtsize (n, 16-2);
656                         break;
657
658                         /*
659                          * Implementation: File, AssemblyRef, ExportedType
660                          */
661                 case MONO_MT_IMPL_IDX:
662                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
663                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
664                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
665
666                         /* 2 bits to encode tag */
667                         field_size = rtsize (n, 16-2);
668                         break;
669
670                         /*
671                          * HasFieldMarshall: FieldDef, ParamDef
672                          */
673                 case MONO_MT_HFM_IDX:
674                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
675                                  meta->tables [MONO_TABLE_PARAM].rows);
676
677                         /* 1 bit used to encode tag */
678                         field_size = rtsize (n, 16-1);
679                         break;
680
681                         /*
682                          * MemberForwarded: FieldDef, MethodDef
683                          */
684                 case MONO_MT_MF_IDX:
685                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
686                                  meta->tables [MONO_TABLE_METHOD].rows);
687
688                         /* 1 bit used to encode tag */
689                         field_size = rtsize (n, 16-1);
690                         break;
691
692                         /*
693                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
694                          * LAMESPEC
695                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
696                          */
697                 case MONO_MT_TDOR_IDX:
698                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
699                                  meta->tables [MONO_TABLE_TYPEREF].rows);
700                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
701
702                         /* 2 bits to encode */
703                         field_size = rtsize (n, 16-2);
704                         break;
705
706                         /*
707                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
708                          */
709                 case MONO_MT_MRP_IDX:
710                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
711                                  meta->tables [MONO_TABLE_TYPEREF].rows);
712                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
713                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
714                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
715                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
716
717                         /* 3 bits to encode */
718                         field_size = rtsize (n, 16 - 3);
719                         break;
720                         
721                         /*
722                          * MethodDefOrRef: MethodDef, MemberRef
723                          */
724                 case MONO_MT_MDOR_IDX:
725                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
726                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
727
728                         /* 1 bit used to encode tag */
729                         field_size = rtsize (n, 16-1);
730                         break;
731                         
732                         /*
733                          * HasSemantics: Property, Event
734                          */
735                 case MONO_MT_HS_IDX:
736                         n = MAX (meta->tables [MONO_TABLE_PROPERTY].rows,
737                                  meta->tables [MONO_TABLE_EVENT].rows);
738
739                         /* 1 bit used to encode tag */
740                         field_size = rtsize (n, 16-1);
741                         break;
742
743                         /*
744                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
745                          */
746                 case MONO_MT_RS_IDX:
747                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
748                                  meta->tables [MONO_TABLE_MODULEREF].rows);
749                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
750                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
751
752                         /* 2 bits used to encode tag (ECMA spec claims 3) */
753                         field_size = rtsize (n, 16 - 2);
754                         break;
755                 }
756
757                 /*
758                  * encode field size as follows (we just need to
759                  * distinguish them).
760                  *
761                  * 4 -> 3
762                  * 2 -> 1
763                  * 1 -> 0
764                  */
765                 bitfield |= (field_size-1) << shift;
766                 shift += 2;
767                 size += field_size;
768                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
769         }
770
771         *result_bitfield = (i << 24) | bitfield;
772         return size;
773 }
774
775 /**
776  * mono_metadata_compute_table_bases:
777  * @meta: metadata context to compute table values
778  *
779  * Computes the table bases for the metadata structure.
780  * This is an internal function used by the image loader code.
781  */
782 void
783 mono_metadata_compute_table_bases (MonoImage *meta)
784 {
785         int i;
786         const char *base = meta->tables_base;
787         
788         for (i = 0; i < MONO_TABLE_NUM; i++) {
789                 MonoTableInfo *table = &meta->tables [i];
790                 if (table->rows == 0)
791                         continue;
792
793                 table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
794                 table->base = base;
795                 base += table->rows * table->row_size;
796         }
797 }
798
799 /**
800  * mono_metadata_locate:
801  * @meta: metadata context
802  * @table: table code.
803  * @idx: index of element to retrieve from @table.
804  *
805  * Returns: a pointer to the @idx element in the metadata table
806  * whose code is @table.
807  */
808 const char *
809 mono_metadata_locate (MonoImage *meta, int table, int idx)
810 {
811         /* idx == 0 refers always to NULL */
812         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
813            
814         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
815 }
816
817 /**
818  * mono_metadata_locate_token:
819  * @meta: metadata context
820  * @token: metadata token
821  *
822  * Returns: a pointer to the data in the metadata represented by the
823  * token #token.
824  */
825 const char *
826 mono_metadata_locate_token (MonoImage *meta, guint32 token)
827 {
828         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
829 }
830
831 /**
832  * mono_metadata_string_heap:
833  * @meta: metadata context
834  * @index: index into the string heap.
835  *
836  * Returns: an in-memory pointer to the @index in the string heap.
837  */
838 const char *
839 mono_metadata_string_heap (MonoImage *meta, guint32 index)
840 {
841         g_return_val_if_fail (index < meta->heap_strings.size, "");
842         return meta->heap_strings.data + index;
843 }
844
845 /**
846  * mono_metadata_user_string:
847  * @meta: metadata context
848  * @index: index into the user string heap.
849  *
850  * Returns: an in-memory pointer to the @index in the user string heap ("#US").
851  */
852 const char *
853 mono_metadata_user_string (MonoImage *meta, guint32 index)
854 {
855         g_return_val_if_fail (index < meta->heap_us.size, "");
856         return meta->heap_us.data + index;
857 }
858
859 /**
860  * mono_metadata_blob_heap:
861  * @meta: metadata context
862  * @index: index into the blob.
863  *
864  * Returns: an in-memory pointer to the @index in the Blob heap.
865  */
866 const char *
867 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
868 {
869         g_return_val_if_fail (index < meta->heap_blob.size, "");
870         return meta->heap_blob.data + index;
871 }
872
873 /**
874  * mono_metadata_guid_heap:
875  * @meta: metadata context
876  * @index: index into the guid heap.
877  *
878  * Returns: an in-memory pointer to the @index in the guid heap.
879  */
880 const char *
881 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
882 {
883         --index;
884         index *= 16; /* adjust for guid size and 1-based index */
885         g_return_val_if_fail (index < meta->heap_guid.size, "");
886         return meta->heap_guid.data + index;
887 }
888
889 static const char *
890 dword_align (const char *ptr)
891 {
892 #if SIZEOF_VOID_P == 8
893         return (const char *) (((guint64) (ptr + 3)) & ~3);
894 #else
895         return (const char *) (((guint32) (ptr + 3)) & ~3);
896 #endif
897 }
898
899 /**
900  * mono_metadata_decode_row:
901  * @t: table to extract information from.
902  * @idx: index in table.
903  * @res: array of @res_size cols to store the results in
904  *
905  * This decompresses the metadata element @idx in table @t
906  * into the guint32 @res array that has res_size elements
907  */
908 void
909 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
910 {
911         guint32 bitfield = t->size_bitfield;
912         int i, count = mono_metadata_table_count (bitfield);
913         const char *data = t->base + idx * t->row_size;
914         
915         g_assert (res_size == count);
916         
917         for (i = 0; i < count; i++) {
918                 int n = mono_metadata_table_size (bitfield, i);
919
920                 switch (n){
921                 case 1:
922                         res [i] = *data; break;
923                 case 2:
924                         res [i] = read16 (data); break;
925                 case 4:
926                         res [i] = read32 (data); break;
927                 default:
928                         g_assert_not_reached ();
929                 }
930                 data += n;
931         }
932 }
933
934 /**
935  * mono_metadata_decode_row_col:
936  * @t: table to extract information from.
937  * @idx: index for row in table.
938  * @col: column in the row.
939  *
940  * This function returns the value of column @col from the @idx
941  * row in the table @t.
942  */
943 guint32
944 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
945 {
946         guint32 bitfield = t->size_bitfield;
947         int i;
948         register const char *data = t->base + idx * t->row_size;
949         register int n;
950         
951         g_assert (col < mono_metadata_table_count (bitfield));
952
953         n = mono_metadata_table_size (bitfield, 0);
954         for (i = 0; i < col; ++i) {
955                 data += n;
956                 n = mono_metadata_table_size (bitfield, i + 1);
957         }
958         switch (n) {
959         case 1:
960                 return *data;
961         case 2:
962                 return read16 (data);
963         case 4:
964                 return read32 (data);
965         default:
966                 g_assert_not_reached ();
967         }
968         return 0;
969 }
970 /**
971  * mono_metadata_decode_blob_size:
972  * @ptr: pointer to a blob object
973  * @rptr: the new position of the pointer
974  *
975  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
976  *
977  * Returns: the size of the blob object
978  */
979 guint32
980 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
981 {
982         const unsigned char *ptr = (const unsigned char *)xptr;
983         guint32 size;
984         
985         if ((*ptr & 0x80) == 0){
986                 size = ptr [0] & 0x7f;
987                 ptr++;
988         } else if ((*ptr & 0x40) == 0){
989                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
990                 ptr += 2;
991         } else {
992                 size = ((ptr [0] & 0x1f) << 24) +
993                         (ptr [1] << 16) +
994                         (ptr [2] << 8) +
995                         ptr [3];
996                 ptr += 4;
997         }
998         if (rptr)
999                 *rptr = ptr;
1000         return size;
1001 }
1002
1003 /**
1004  * mono_metadata_decode_value:
1005  * @ptr: pointer to decode from
1006  * @rptr: the new position of the pointer
1007  *
1008  * This routine decompresses 32-bit values as specified in the "Blob and
1009  * Signature" section (22.2)
1010  *
1011  * Returns: the decoded value
1012  */
1013 guint32
1014 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1015 {
1016         const unsigned char *ptr = (const unsigned char *) _ptr;
1017         unsigned char b = *ptr;
1018         guint32 len;
1019         
1020         if ((b & 0x80) == 0){
1021                 len = b;
1022                 ++ptr;
1023         } else if ((b & 0x40) == 0){
1024                 len = ((b & 0x3f) << 8 | ptr [1]);
1025                 ptr += 2;
1026         } else {
1027                 len = ((b & 0x1f) << 24) |
1028                         (ptr [1] << 16) |
1029                         (ptr [2] << 8) |
1030                         ptr [3];
1031                 ptr += 4;
1032         }
1033         if (rptr)
1034                 *rptr = ptr;
1035         
1036         return len;
1037 }
1038
1039 /**
1040  * mono_metadata_decode_signed_value:
1041  * @ptr: pointer to decode from
1042  * @rptr: the new position of the pointer
1043  *
1044  * This routine decompresses 32-bit signed values
1045  * (not specified in the spec)
1046  *
1047  * Returns: the decoded value
1048  */
1049 gint32
1050 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1051 {
1052         guint32 uval = mono_metadata_decode_value (ptr, rptr);
1053         gint32 ival = uval >> 1;
1054         if (!(uval & 1))
1055                 return ival;
1056         /* ival is a truncated 2's complement negative number.  */
1057         if (ival < 0x40)
1058                 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1059                 return ival - 0x40;
1060         if (ival < 0x2000)
1061                 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1062                 return ival - 0x2000;
1063         if (ival < 0x10000000)
1064                 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1065                 return ival - 0x10000000;
1066         g_assert (ival < 0x20000000);
1067         g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1068         return ival - 0x20000000;
1069 }
1070
1071 /*
1072  * mono_metadata_parse_typedef_or_ref:
1073  * @m: a metadata context.
1074  * @ptr: a pointer to an encoded TypedefOrRef in @m
1075  * @rptr: pointer updated to match the end of the decoded stream
1076  *
1077  * Returns: a token valid in the @m metadata decoded from
1078  * the compressed representation.
1079  */
1080 guint32
1081 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1082 {
1083         guint32 token;
1084         token = mono_metadata_decode_value (ptr, &ptr);
1085         if (rptr)
1086                 *rptr = ptr;
1087         return mono_metadata_token_from_dor (token);
1088 }
1089
1090 /*
1091  * mono_metadata_parse_custom_mod:
1092  * @m: a metadata context.
1093  * @dest: storage where the info about the custom modifier is stored (may be NULL)
1094  * @ptr: a pointer to (possibly) the start of a custom modifier list
1095  * @rptr: pointer updated to match the end of the decoded stream
1096  *
1097  * Checks if @ptr points to a type custom modifier compressed representation.
1098  *
1099  * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1100  */
1101 int
1102 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1103 {
1104         MonoCustomMod local;
1105         if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1106                 if (!dest)
1107                         dest = &local;
1108                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1109                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1110                 return TRUE;
1111         }
1112         return FALSE;
1113 }
1114
1115 /*
1116  * mono_metadata_parse_array:
1117  * @m: a metadata context.
1118  * @ptr: a pointer to an encoded array description.
1119  * @rptr: pointer updated to match the end of the decoded stream
1120  *
1121  * Decodes the compressed array description found in the metadata @m at @ptr.
1122  *
1123  * Returns: a #MonoArrayType structure describing the array type
1124  * and dimensions.
1125  */
1126 MonoArrayType *
1127 mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
1128                                 const char *ptr, const char **rptr)
1129 {
1130         int i;
1131         MonoArrayType *array = g_new0 (MonoArrayType, 1);
1132         MonoType *etype;
1133         
1134         etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
1135         if (!etype)
1136                 return NULL;
1137         array->eklass = mono_class_from_mono_type (etype);
1138         array->rank = mono_metadata_decode_value (ptr, &ptr);
1139
1140         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1141         if (array->numsizes)
1142                 array->sizes = g_new0 (int, array->numsizes);
1143         for (i = 0; i < array->numsizes; ++i)
1144                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1145
1146         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1147         if (array->numlobounds)
1148                 array->lobounds = g_new0 (int, array->numlobounds);
1149         for (i = 0; i < array->numlobounds; ++i)
1150                 array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1151
1152         if (rptr)
1153                 *rptr = ptr;
1154         return array;
1155 }
1156
1157 MonoArrayType *
1158 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1159 {
1160         return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
1161 }
1162
1163 /*
1164  * mono_metadata_free_array:
1165  * @array: array description
1166  *
1167  * Frees the array description returned from mono_metadata_parse_array().
1168  */
1169 void
1170 mono_metadata_free_array (MonoArrayType *array)
1171 {
1172         g_free (array->sizes);
1173         g_free (array->lobounds);
1174         g_free (array);
1175 }
1176
1177 /*
1178  * need to add common field and param attributes combinations:
1179  * [out] param
1180  * public static
1181  * public static literal
1182  * private
1183  * private static
1184  * private static literal
1185  */
1186 static const MonoType
1187 builtin_types[] = {
1188         /* data, attrs, type,              nmods, byref, pinned */
1189         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
1190         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
1191         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
1192         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
1193         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
1194         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
1195         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
1196         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
1197         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
1198         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
1199         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1200         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1201         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1202         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1203         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1204         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1205         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1206         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1207         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1208         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1209         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1210         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1211         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1212         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1213         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1214         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1215         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1216         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1217         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0},
1218         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1219         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1220         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1221         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1222         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1223 };
1224
1225 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1226
1227 static GHashTable *type_cache = NULL;
1228 static GHashTable *generic_inst_cache = NULL;
1229 static GHashTable *generic_class_cache = NULL;
1230 static int next_generic_inst_id = 0;
1231
1232 static guint mono_generic_class_hash (gconstpointer data);
1233
1234 /*
1235  * MonoTypes with modifies are never cached, so we never check or use that field.
1236  */
1237 static guint
1238 mono_type_hash (gconstpointer data)
1239 {
1240         const MonoType *type = (const MonoType *) data;
1241         if (type->type == MONO_TYPE_GENERICINST)
1242                 return mono_generic_class_hash (type->data.generic_class);
1243         else
1244                 return type->type | (type->byref << 8) | (type->attrs << 9);
1245 }
1246
1247 static gint
1248 mono_type_equal (gconstpointer ka, gconstpointer kb)
1249 {
1250         const MonoType *a = (const MonoType *) ka;
1251         const MonoType *b = (const MonoType *) kb;
1252         
1253         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1254                 return 0;
1255         /* need other checks */
1256         return 1;
1257 }
1258
1259 static guint
1260 mono_generic_inst_hash (gconstpointer data)
1261 {
1262         const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1263         guint hash = 0;
1264         int i;
1265         
1266         for (i = 0; i < ginst->type_argc; ++i) {
1267                 hash *= 13;
1268                 hash += mono_metadata_type_hash (ginst->type_argv [i]);
1269         }
1270
1271         return hash ^ (ginst->is_open << 8);
1272 }
1273
1274 static gboolean
1275 mono_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1276 {
1277         const MonoGenericInst *a = (const MonoGenericInst *) ka;
1278         const MonoGenericInst *b = (const MonoGenericInst *) kb;
1279         int i;
1280
1281         if ((a->is_open != b->is_open) || (a->type_argc != b->type_argc) || (a->is_reference != b->is_reference))
1282                 return FALSE;
1283         for (i = 0; i < a->type_argc; ++i) {
1284                 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], FALSE))
1285                         return FALSE;
1286         }
1287         return TRUE;
1288 }
1289
1290 static guint
1291 mono_generic_class_hash (gconstpointer data)
1292 {
1293         const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1294         guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1295
1296         hash *= 13;
1297         hash += mono_generic_inst_hash (gclass->inst);
1298
1299         return hash;
1300 }
1301
1302 static gboolean
1303 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1304 {
1305         const MonoGenericClass *a = (const MonoGenericClass *) ka;
1306         const MonoGenericClass *b = (const MonoGenericClass *) kb;
1307
1308         return _mono_metadata_generic_class_equal (a, b, FALSE);
1309 }
1310
1311 /**
1312  * mono_metadata_init:
1313  *
1314  * Initialize the global variables of this module.
1315  * This is a Mono runtime internal function.
1316  */
1317 void
1318 mono_metadata_init (void)
1319 {
1320         int i;
1321
1322         type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1323         generic_inst_cache = g_hash_table_new (mono_generic_inst_hash, mono_generic_inst_equal);
1324         generic_class_cache = g_hash_table_new (mono_generic_class_hash, mono_generic_class_equal);
1325
1326         for (i = 0; i < NBUILTIN_TYPES (); ++i)
1327                 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1328 }
1329
1330 /**
1331  * mono_metadata_cleanup:
1332  *
1333  * Free all resources used by this module.
1334  * This is a Mono runtime internal function.
1335  */
1336 void
1337 mono_metadata_cleanup (void)
1338 {
1339         g_hash_table_destroy (type_cache);
1340         g_hash_table_destroy (generic_inst_cache);
1341         g_hash_table_destroy (generic_class_cache);
1342 }
1343
1344 /**
1345  * mono_metadata_parse_type:
1346  * @m: metadata context
1347  * @mode: king of type that may be found at @ptr
1348  * @opt_attrs: optional attributes to store in the returned type
1349  * @ptr: pointer to the type representation
1350  * @rptr: pointer updated to match the end of the decoded stream
1351  * 
1352  * Decode a compressed type description found at @ptr in @m.
1353  * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1354  * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1355  * This function can be used to decode type descriptions in method signatures,
1356  * field signatures, locals signatures etc.
1357  *
1358  * To parse a generic type, `generic_container' points to the current class'es
1359  * (the `generic_container' field in the MonoClass) or the current generic method's
1360  * (the `generic_container' field in the MonoMethodNormal) generic container.
1361  * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1362  * this MonoGenericContainer.
1363  * This is a Mono runtime internal function.
1364  *
1365  * LOCKING: Assumes the loader lock is held.
1366  *
1367  * Returns: a #MonoType structure representing the decoded type.
1368  */
1369 MonoType*
1370 mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
1371                                short opt_attrs, const char *ptr, const char **rptr)
1372 {
1373         MonoType *type, *cached;
1374         MonoType stype;
1375         gboolean byref = FALSE;
1376         gboolean pinned = FALSE;
1377         const char *tmp_ptr;
1378         int count = 0;
1379         gboolean found;
1380
1381         /*
1382          * According to the spec, custom modifiers should come before the byref
1383          * flag, but the IL produced by ilasm from the following signature:
1384          *   object modopt(...) &
1385          * starts with a byref flag, followed by the modifiers. (bug #49802)
1386          * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1387          * it would be better to treat byref as real type constructor instead of
1388          * a modifier...
1389          * Also, pinned should come before anything else, but some MSV++ produced
1390          * assemblies violate this (#bug 61990).
1391          */
1392
1393         /* Count the modifiers first */
1394         tmp_ptr = ptr;
1395         found = TRUE;
1396         while (found) {
1397                 switch (*tmp_ptr) {
1398                 case MONO_TYPE_PINNED:
1399                 case MONO_TYPE_BYREF:
1400                         ++tmp_ptr;
1401                         break;
1402                 case MONO_TYPE_CMOD_REQD:
1403                 case MONO_TYPE_CMOD_OPT:
1404                         count ++;
1405                         mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1406                         break;
1407                 default:
1408                         found = FALSE;
1409                 }
1410         }
1411
1412         if (count) {
1413                 type = mono_mempool_alloc0 (m->mempool, sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
1414                 type->num_mods = count;
1415                 if (count > 64)
1416                         g_warning ("got more than 64 modifiers in type");
1417         } else {
1418                 type = &stype;
1419                 memset (type, 0, sizeof (MonoType));
1420         }
1421
1422         /* Parse pinned, byref and custom modifiers */
1423         found = TRUE;
1424         count = 0;
1425         while (found) {
1426                 switch (*ptr) {
1427                 case MONO_TYPE_PINNED:
1428                         pinned = TRUE;
1429                         ++ptr;
1430                         break;
1431                 case MONO_TYPE_BYREF:
1432                         byref = TRUE;
1433                         ++ptr;
1434                         break;
1435                 case MONO_TYPE_CMOD_REQD:
1436                 case MONO_TYPE_CMOD_OPT:
1437                         mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1438                         count ++;
1439                         break;
1440                 default:
1441                         found = FALSE;
1442                 }
1443         }
1444         
1445         type->attrs = opt_attrs;
1446         type->byref = byref;
1447         type->pinned = pinned ? 1 : 0;
1448
1449         if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) {
1450                 if (type != &stype)
1451                         g_free (type);
1452                 return NULL;
1453         }
1454
1455         if (rptr)
1456                 *rptr = ptr;
1457
1458                 if (!type->num_mods) {
1459                 /* no need to free type here, because it is on the stack */
1460                 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1461                         MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1462
1463                         /* Consider the case:
1464
1465                              class Foo<T> { class Bar {} }
1466                              class Test : Foo<Test>.Bar {}
1467
1468                            When Foo<Test> is being expanded, 'Test' isn't yet initialized.  It's actually in
1469                            a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1470
1471                            We ensure that the MonoClass is in a state that we can canonicalize to:
1472
1473                              klass->byval_arg.data.klass == klass
1474                              klass->this_arg.data.klass == klass
1475
1476                            If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1477
1478                            LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1479                                     of a MonoClass which currently holds the loader lock.  'type' is local.
1480                         */
1481                         if (ret->data.klass == type->data.klass)
1482                                 return ret;
1483                 }
1484                 /* No need to use locking since nobody is modifying the hash table */
1485                 if ((cached = g_hash_table_lookup (type_cache, type)))
1486                         return cached;
1487         }
1488         
1489         /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1490         
1491         if (type == &stype) {
1492                 type = mono_mempool_alloc (m->mempool, sizeof (MonoType));
1493                 memcpy (type, &stype, sizeof (MonoType));
1494         }
1495         return type;
1496 }
1497
1498 /*
1499  * LOCKING: Assumes the loader lock is held.
1500  */
1501 MonoType*
1502 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1503                           const char *ptr, const char **rptr)
1504 {
1505         return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
1506 }
1507
1508 /*
1509  * mono_metadata_get_param_attrs:
1510  *
1511  *   Return the parameter attributes for the method whose MethodDef index is DEF. The 
1512  * returned memory needs to be freed by the caller. If all the param attributes are
1513  * 0, then NULL is returned.
1514  */
1515 int*
1516 mono_metadata_get_param_attrs (MonoImage *m, int def)
1517 {
1518         MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1519         MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1520         guint32 cols [MONO_PARAM_SIZE];
1521         guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1522         int *pattrs = NULL;
1523
1524         if (def < methodt->rows)
1525                 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1526         else
1527                 lastp = paramt->rows + 1;
1528
1529         for (i = param_index; i < lastp; ++i) {
1530                 mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1531                 if (cols [MONO_PARAM_FLAGS]) {
1532                         if (!pattrs)
1533                                 pattrs = g_new0 (int, 1 + (lastp - param_index));
1534                         pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1535                 }
1536         }
1537
1538         return pattrs;
1539 }
1540
1541 /*
1542  * mono_metadata_parse_signature_full:
1543  * @image: metadata context
1544  * @generic_container: generic container
1545  * @toke: metadata token
1546  *
1547  * Decode a method signature stored in the STANDALONESIG table
1548  *
1549  * LOCKING: Assumes the loader lock is held.
1550  *
1551  * Returns: a MonoMethodSignature describing the signature.
1552  */
1553 MonoMethodSignature*
1554 mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
1555 {
1556         MonoTableInfo *tables = image->tables;
1557         guint32 idx = mono_metadata_token_index (token);
1558         guint32 sig;
1559         const char *ptr;
1560
1561         if (image->dynamic)
1562                 return mono_lookup_dynamic_token (image, token);
1563
1564         g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1565                 
1566         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1567
1568         ptr = mono_metadata_blob_heap (image, sig);
1569         mono_metadata_decode_blob_size (ptr, &ptr);
1570
1571         return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL); 
1572 }
1573
1574 /*
1575  * mono_metadata_parse_signature:
1576  * @image: metadata context
1577  * @toke: metadata token
1578  *
1579  * Decode a method signature stored in the STANDALONESIG table
1580  *
1581  * Returns: a MonoMethodSignature describing the signature.
1582  */
1583 MonoMethodSignature*
1584 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1585 {
1586         return mono_metadata_parse_signature_full (image, NULL, token);
1587 }
1588
1589 /*
1590  * mono_metadata_signature_alloc:
1591  * @image: metadata context
1592  * @nparmas: number of parameters in the signature
1593  *
1594  * Allocate a MonoMethodSignature structure with the specified number of params.
1595  * The return type and the params types need to be filled later.
1596  * This is a Mono runtime internal function.
1597  *
1598  * LOCKING: Assumes the loader lock is held.
1599  *
1600  * Returns: the new MonoMethodSignature structure.
1601  */
1602 MonoMethodSignature*
1603 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1604 {
1605         MonoMethodSignature *sig;
1606
1607         sig = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1608         sig->param_count = nparams;
1609         sig->sentinelpos = -1;
1610
1611         return sig;
1612 }
1613
1614 /*
1615  * mono_metadata_signature_dup:
1616  * @sig: method signature
1617  *
1618  * Duplicate an existing MonoMethodSignature so it can be modified.
1619  * This is a Mono runtime internal function.
1620  *
1621  * Returns: the new MonoMethodSignature structure.
1622  */
1623 MonoMethodSignature*
1624 mono_metadata_signature_dup (MonoMethodSignature *sig)
1625 {
1626         int sigsize;
1627
1628         sigsize = sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
1629         return g_memdup (sig, sigsize);
1630 }
1631
1632 /*
1633  * mono_metadata_parse_method_signature:
1634  * @m: metadata context
1635  * @generic_container: generics container
1636  * @def: the MethodDef index or 0 for Ref signatures.
1637  * @ptr: pointer to the signature metadata representation
1638  * @rptr: pointer updated to match the end of the decoded stream
1639  *
1640  * Decode a method signature stored at @ptr.
1641  * This is a Mono runtime internal function.
1642  *
1643  * LOCKING: Assumes the loader lock is held.
1644  *
1645  * Returns: a MonoMethodSignature describing the signature.
1646  */
1647 MonoMethodSignature *
1648 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
1649                                            int def, const char *ptr, const char **rptr)
1650 {
1651         MonoMethodSignature *method;
1652         int i, *pattrs = NULL;
1653         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1654         guint32 gen_param_count = 0;
1655         gboolean is_open = FALSE;
1656
1657         if (*ptr & 0x10)
1658                 gen_param_count = 1;
1659         if (*ptr & 0x20)
1660                 hasthis = 1;
1661         if (*ptr & 0x40)
1662                 explicit_this = 1;
1663         call_convention = *ptr & 0x0F;
1664         ptr++;
1665         if (gen_param_count)
1666                 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
1667         param_count = mono_metadata_decode_value (ptr, &ptr);
1668
1669         if (def)
1670                 pattrs = mono_metadata_get_param_attrs (m, def);
1671         method = mono_metadata_signature_alloc (m, param_count);
1672         method->hasthis = hasthis;
1673         method->explicit_this = explicit_this;
1674         method->call_convention = call_convention;
1675         method->generic_param_count = gen_param_count;
1676
1677         if (call_convention != 0xa) {
1678                 method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr);
1679                 if (!method->ret) {
1680                         mono_metadata_free_method_signature (method);
1681                         g_free (pattrs);
1682                         return NULL;
1683                 }
1684                 is_open = mono_class_is_open_constructed_type (method->ret);
1685         }
1686
1687         for (i = 0; i < method->param_count; ++i) {
1688                 if (*ptr == MONO_TYPE_SENTINEL) {
1689                         if (method->call_convention != MONO_CALL_VARARG || def)
1690                                 g_error ("found sentinel for methoddef or no vararg method");
1691                         if (method->sentinelpos >= 0)
1692                                 g_error ("found sentinel twice in the same signature");
1693                         method->sentinelpos = i;
1694                         ptr++;
1695                 }
1696                 method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
1697                 if (!method->params [i]) {
1698                         mono_metadata_free_method_signature (method);
1699                         g_free (pattrs);
1700                         return NULL;
1701                 }
1702                 if (!is_open)
1703                         is_open = mono_class_is_open_constructed_type (method->params [i]);
1704         }
1705
1706         /* The sentinel could be missing if the caller does not pass any additional arguments */
1707         if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
1708                 method->sentinelpos = method->param_count;
1709
1710         method->has_type_parameters = is_open;
1711
1712         if (def && (method->call_convention == MONO_CALL_VARARG))
1713                 method->sentinelpos = method->param_count;
1714
1715         g_free (pattrs);
1716
1717         if (rptr)
1718                 *rptr = ptr;
1719         /*
1720          * Add signature to a cache and increase ref count...
1721          */
1722
1723         return method;
1724 }
1725
1726 /*
1727  * mono_metadata_parse_method_signature:
1728  * @m: metadata context
1729  * @def: the MethodDef index or 0 for Ref signatures.
1730  * @ptr: pointer to the signature metadata representation
1731  * @rptr: pointer updated to match the end of the decoded stream
1732  *
1733  * Decode a method signature stored at @ptr.
1734  * This is a Mono runtime internal function.
1735  *
1736  * LOCKING: Assumes the loader lock is held.
1737  *
1738  * Returns: a MonoMethodSignature describing the signature.
1739  */
1740 MonoMethodSignature *
1741 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
1742 {
1743         return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
1744 }
1745
1746 /*
1747  * mono_metadata_free_method_signature:
1748  * @sig: signature to destroy
1749  *
1750  * Free the memory allocated in the signature @sig.
1751  * This method needs to be robust and work also on partially-built
1752  * signatures, so it does extra checks.
1753  */
1754 void
1755 mono_metadata_free_method_signature (MonoMethodSignature *sig)
1756 {
1757         int i;
1758         if (sig->ret)
1759                 mono_metadata_free_type (sig->ret);
1760         for (i = 0; i < sig->param_count; ++i) {
1761                 if (sig->params [i])
1762                         mono_metadata_free_type (sig->params [i]);
1763         }
1764 }
1765
1766 /*
1767  * mono_metadata_lookup_generic_inst:
1768  *
1769  * Check whether the newly created generic instantiation @ginst already exists
1770  * in the cache and return the cached value in this case.  Otherwise insert
1771  * it into the cache.
1772  *
1773  * Use this method each time you create a new `MonoGenericInst' to ensure
1774  * proper caching.  Only use the returned value as the argument passed to this
1775  * method may be freed.
1776  *
1777  */
1778 MonoGenericInst *
1779 mono_metadata_lookup_generic_inst (MonoGenericInst *ginst)
1780 {
1781         MonoGenericInst *cached;
1782         int i;
1783
1784         cached = g_hash_table_lookup (generic_inst_cache, ginst);
1785         if (cached) {
1786                 for (i = 0; i < ginst->type_argc; i++)
1787                         mono_metadata_free_type (ginst->type_argv [i]);
1788                 g_free (ginst->type_argv);
1789                 g_free (ginst);
1790                 return cached;
1791         }
1792
1793         ginst->id = ++next_generic_inst_id;
1794         g_hash_table_insert (generic_inst_cache, ginst, ginst);
1795
1796         return ginst;
1797 }
1798
1799 /*
1800  * mono_metadata_lookup_generic_class:
1801  *
1802  * Check whether the newly created generic class @gclass already exists
1803  * in the cache and return the cached value in this case.  Otherwise insert
1804  * it into the cache and return NULL.
1805  *
1806  * Returns: the previosly cached generic class or NULL if it has been newly
1807  *          inserted into the cache.
1808  *
1809  */
1810 MonoGenericClass *
1811 mono_metadata_lookup_generic_class (MonoGenericClass *gclass)
1812 {
1813         MonoGenericClass *cached;
1814
1815         cached = g_hash_table_lookup (generic_class_cache, gclass);
1816         if (cached)
1817                 return cached;
1818
1819         g_hash_table_insert (generic_class_cache, gclass, gclass);
1820         return NULL;
1821 }
1822
1823 /*
1824  * mono_metadata_inflate_generic_inst:
1825  *
1826  * Instantiate the generic instance @ginst with the context @context.
1827  *
1828  */
1829 MonoGenericInst *
1830 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
1831 {
1832         MonoGenericInst *nginst;
1833         int i;
1834
1835         if (!ginst->is_open)
1836                 return ginst;
1837
1838         nginst = g_new0 (MonoGenericInst, 1);
1839         nginst->type_argc = ginst->type_argc;
1840         nginst->type_argv = g_new0 (MonoType*, nginst->type_argc);
1841         nginst->is_reference = 1;
1842
1843         for (i = 0; i < nginst->type_argc; i++) {
1844                 MonoType *t = mono_class_inflate_generic_type (ginst->type_argv [i], context);
1845
1846                 if (!nginst->is_open)
1847                         nginst->is_open = mono_class_is_open_constructed_type (t);
1848                 if (nginst->is_reference)
1849                         nginst->is_reference = MONO_TYPE_IS_REFERENCE (t);
1850
1851                 nginst->type_argv [i] = t;
1852         }
1853
1854         return mono_metadata_lookup_generic_inst (nginst);
1855 }
1856
1857 MonoGenericInst *
1858 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
1859                                   int count, const char *ptr, const char **rptr)
1860 {
1861         MonoGenericInst *ginst;
1862         int i;
1863
1864         ginst = g_new0 (MonoGenericInst, 1);
1865         ginst->type_argc = count;
1866         ginst->type_argv = g_new0 (MonoType*, count);
1867         ginst->is_reference = 1;
1868
1869         for (i = 0; i < ginst->type_argc; i++) {
1870                 MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
1871
1872                 if (!t) {
1873                         g_free (ginst->type_argv);
1874                         g_free (ginst);
1875                         return NULL;
1876                 }
1877                 ginst->type_argv [i] = t;
1878                 if (!ginst->is_open)
1879                         ginst->is_open = mono_class_is_open_constructed_type (t);
1880                 if (ginst->is_reference)
1881                         ginst->is_reference = MONO_TYPE_IS_REFERENCE (t);
1882         }
1883
1884         if (rptr)
1885                 *rptr = ptr;
1886
1887         return mono_metadata_lookup_generic_inst (ginst);
1888 }
1889
1890 static gboolean
1891 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
1892                                       const char *ptr, const char **rptr)
1893 {
1894         MonoInflatedGenericClass *igclass;
1895         MonoGenericClass *gclass, *cached;
1896         MonoClass *gklass;
1897         MonoType *gtype;
1898         int count;
1899
1900         igclass = g_new0 (MonoInflatedGenericClass, 1);
1901         gclass = &igclass->generic_class;
1902         gclass->is_inflated = TRUE;
1903
1904         type->data.generic_class = gclass;
1905
1906         gclass->context = g_new0 (MonoGenericContext, 1);
1907         gclass->context->gclass = gclass;
1908
1909         /*
1910          * Create the klass before parsing the type arguments.
1911          * This is required to support "recursive" definitions.
1912          * See mcs/tests/gen-23.cs for an example.
1913          */
1914         igclass->klass = g_new0 (MonoClass, 1);
1915
1916         gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
1917         if (gtype == NULL)
1918                 return FALSE;
1919         gclass->container_class = gklass = mono_class_from_mono_type (gtype);
1920
1921         g_assert (gklass->generic_container);
1922         gclass->context->container = gklass->generic_container;
1923
1924         count = mono_metadata_decode_value (ptr, &ptr);
1925
1926         gclass->inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
1927
1928         if (rptr)
1929                 *rptr = ptr;
1930
1931         /* If we failed to parse, return, the error has been flagged. */
1932         if (gclass->inst == NULL)
1933                 return FALSE;
1934         
1935         /*
1936          * We may be called multiple times on different metadata to create the same
1937          * instantiated type.  This happens for instance if we're part of a method or
1938          * local variable signature.
1939          *
1940          * It's important to return the same MonoGenericClass * for each particualar
1941          * instantiation of a generic type (ie "Stack<Int32>") to make static fields
1942          * work.
1943          *
1944          * According to the spec ($26.1.5), a static variable in a generic class
1945          * declaration is shared amongst all instances of the same closed constructed
1946          * type.
1947          */
1948
1949         cached = g_hash_table_lookup (generic_class_cache, gclass);
1950         if (cached) {
1951                 g_free (igclass->klass);
1952                 g_free (gclass);
1953
1954                 type->data.generic_class = cached;
1955                 return TRUE;
1956         } else {
1957                 g_hash_table_insert (generic_class_cache, gclass, gclass);
1958
1959                 mono_stats.generic_instance_count++;
1960                 mono_stats.generics_metadata_size += sizeof (MonoGenericClass) +
1961                         sizeof (MonoGenericContext) +
1962                         gclass->inst->type_argc * sizeof (MonoType);
1963         }
1964         return TRUE;
1965 }
1966
1967 /*
1968  * select_container:
1969  * @gc: The generic container to normalize
1970  * @type: The kind of generic parameters the resulting generic-container should contain
1971  */
1972
1973 static MonoGenericContainer *
1974 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
1975 {
1976         gboolean is_var = (type == MONO_TYPE_VAR);
1977         if (!gc)
1978                 return NULL;
1979
1980         g_assert (is_var || type == MONO_TYPE_MVAR);
1981
1982         if (is_var) {
1983                 if (gc->is_method || gc->parent)
1984                         /*
1985                          * The current MonoGenericContainer is a generic method -> its `parent'
1986                          * points to the containing class'es container.
1987                          */
1988                         return gc->parent;
1989         }
1990
1991         return gc;
1992 }
1993
1994 /* 
1995  * mono_metadata_parse_generic_param:
1996  * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
1997  *                     see mono_metadata_parse_type_full() for details.
1998  * Internal routine to parse a generic type parameter.
1999  */
2000 static MonoGenericParam *
2001 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
2002                                    MonoTypeEnum type, const char *ptr, const char **rptr)
2003 {
2004         int index = mono_metadata_decode_value (ptr, &ptr);
2005         if (rptr)
2006                 *rptr = ptr;
2007
2008         generic_container = select_container (generic_container, type);
2009         if (!generic_container) {
2010                 /* Create dummy MonoGenericParam */
2011                 MonoGenericParam *param = g_new0 (MonoGenericParam, 1);
2012                 param->name = g_strdup_printf ("%d", index);
2013                 param->num = index;
2014
2015                 return param;
2016         }
2017
2018         g_assert (index < generic_container->type_argc);
2019         return &generic_container->type_params [index];
2020 }
2021
2022 /* 
2023  * do_mono_metadata_parse_type:
2024  * @type: MonoType to be filled in with the return value
2025  * @m: image context
2026  * @generic_context: generics_context
2027  * @ptr: pointer to the encoded type
2028  * @rptr: pointer where the end of the encoded type is saved
2029  * 
2030  * Internal routine used to "fill" the contents of @type from an 
2031  * allocated pointer.  This is done this way to avoid doing too
2032  * many mini-allocations (particularly for the MonoFieldType which
2033  * most of the time is just a MonoType, but sometimes might be augmented).
2034  *
2035  * This routine is used by mono_metadata_parse_type and
2036  * mono_metadata_parse_field_type
2037  *
2038  * This extracts a Type as specified in Partition II (22.2.12) 
2039  *
2040  * Returns: FALSE if the type could not be loaded
2041  */
2042 static gboolean
2043 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
2044                              const char *ptr, const char **rptr)
2045 {
2046         gboolean ok = TRUE;
2047         type->type = mono_metadata_decode_value (ptr, &ptr);
2048         
2049         switch (type->type){
2050         case MONO_TYPE_VOID:
2051         case MONO_TYPE_BOOLEAN:
2052         case MONO_TYPE_CHAR:
2053         case MONO_TYPE_I1:
2054         case MONO_TYPE_U1:
2055         case MONO_TYPE_I2:
2056         case MONO_TYPE_U2:
2057         case MONO_TYPE_I4:
2058         case MONO_TYPE_U4:
2059         case MONO_TYPE_I8:
2060         case MONO_TYPE_U8:
2061         case MONO_TYPE_R4:
2062         case MONO_TYPE_R8:
2063         case MONO_TYPE_I:
2064         case MONO_TYPE_U:
2065         case MONO_TYPE_STRING:
2066         case MONO_TYPE_OBJECT:
2067         case MONO_TYPE_TYPEDBYREF:
2068                 break;
2069         case MONO_TYPE_VALUETYPE:
2070         case MONO_TYPE_CLASS: {
2071                 guint32 token;
2072                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
2073                 type->data.klass = mono_class_get (m, token);
2074                 if (!type->data.klass)
2075                         return FALSE;
2076                 break;
2077         }
2078         case MONO_TYPE_SZARRAY: {
2079                 MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
2080                 if (!etype)
2081                         return FALSE;
2082                 type->data.klass = mono_class_from_mono_type (etype);
2083                 mono_metadata_free_type (etype);
2084                 break;
2085         }
2086         case MONO_TYPE_PTR:
2087                 type->data.type = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
2088                 if (!type->data.type)
2089                         return FALSE;
2090                 break;
2091         case MONO_TYPE_FNPTR:
2092                 type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
2093                 break;
2094         case MONO_TYPE_ARRAY:
2095                 type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr);
2096                 break;
2097         case MONO_TYPE_MVAR:
2098         case MONO_TYPE_VAR:
2099                 type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
2100                 break;
2101         case MONO_TYPE_GENERICINST:
2102                 ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
2103                 break;
2104         default:
2105                 g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
2106         }
2107         
2108         if (rptr)
2109                 *rptr = ptr;
2110         return ok;
2111 }
2112
2113 /*
2114  * mono_metadata_free_type:
2115  * @type: type to free
2116  *
2117  * Free the memory allocated for type @type which is assumed to be created by
2118  * mono_metadata_parse_type ().
2119  */
2120 void
2121 mono_metadata_free_type (MonoType *type)
2122 {
2123         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
2124                 return;
2125         
2126         switch (type->type){
2127         case MONO_TYPE_OBJECT:
2128         case MONO_TYPE_STRING:
2129                 if (!type->data.klass)
2130                         break;
2131                 /* fall through */
2132         case MONO_TYPE_CLASS:
2133         case MONO_TYPE_VALUETYPE:
2134                 if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
2135                         return;
2136                 break;
2137         case MONO_TYPE_PTR:
2138                 mono_metadata_free_type (type->data.type);
2139                 break;
2140         case MONO_TYPE_FNPTR:
2141                 mono_metadata_free_method_signature (type->data.method);
2142                 break;
2143         case MONO_TYPE_ARRAY:
2144                 mono_metadata_free_array (type->data.array);
2145                 break;
2146         }
2147
2148         /* Allocated from a mempool, no need to free it */
2149 }
2150
2151 #if 0
2152 static void
2153 hex_dump (const char *buffer, int base, int count)
2154 {
2155         int show_header = 1;
2156         int i;
2157
2158         if (count < 0){
2159                 count = -count;
2160                 show_header = 0;
2161         }
2162         
2163         for (i = 0; i < count; i++){
2164                 if (show_header)
2165                         if ((i % 16) == 0)
2166                                 printf ("\n0x%08x: ", (unsigned char) base + i);
2167
2168                 printf ("%02x ", (unsigned char) (buffer [i]));
2169         }
2170         fflush (stdout);
2171 }
2172 #endif
2173
2174 /** 
2175  * @mh: The Method header
2176  * @ptr: Points to the beginning of the Section Data (25.3)
2177  */
2178 static void
2179 parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr)
2180 {
2181         unsigned char sect_data_flags;
2182         const unsigned char *sptr;
2183         int is_fat;
2184         guint32 sect_data_len;
2185         
2186         while (1) {
2187                 /* align on 32-bit boundary */
2188                 /* FIXME: not 64-bit clean code */
2189                 sptr = ptr = dword_align (ptr); 
2190                 sect_data_flags = *ptr;
2191                 ptr++;
2192                 
2193                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
2194                 if (is_fat) {
2195                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
2196                         ptr += 3;
2197                 } else {
2198                         sect_data_len = ptr [0];
2199                         ++ptr;
2200                 }
2201                 /*
2202                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
2203                 hex_dump (sptr, 0, sect_data_len+8);
2204                 g_print ("\nheader: ");
2205                 hex_dump (sptr-4, 0, 4);
2206                 g_print ("\n");
2207                 */
2208                 
2209                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
2210                         const unsigned char *p = dword_align (ptr);
2211                         int i;
2212                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
2213                         /* we could just store a pointer if we don't need to byteswap */
2214                         mh->clauses = mono_mempool_alloc0 (m->mempool, sizeof (MonoExceptionClause) * mh->num_clauses);
2215                         for (i = 0; i < mh->num_clauses; ++i) {
2216                                 MonoExceptionClause *ec = &mh->clauses [i];
2217                                 guint32 tof_value;
2218                                 if (is_fat) {
2219                                         ec->flags = read32 (p);
2220                                         ec->try_offset = read32 (p + 4);
2221                                         ec->try_len = read32 (p + 8);
2222                                         ec->handler_offset = read32 (p + 12);
2223                                         ec->handler_len = read32 (p + 16);
2224                                         tof_value = read32 (p + 20);
2225                                         p += 24;
2226                                 } else {
2227                                         ec->flags = read16 (p);
2228                                         ec->try_offset = read16 (p + 2);
2229                                         ec->try_len = *(p + 4);
2230                                         ec->handler_offset = read16 (p + 5);
2231                                         ec->handler_len = *(p + 7);
2232                                         tof_value = read32 (p + 8);
2233                                         p += 12;
2234                                 }
2235                                 if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
2236                                         ec->data.filter_offset = tof_value;
2237                                 } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
2238                                         ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
2239                                 } else {
2240                                         ec->data.catch_class = NULL;
2241                                 }
2242                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
2243                         }
2244
2245                 }
2246                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
2247                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
2248                 else
2249                         return;
2250         }
2251 }
2252
2253 /*
2254  * mono_metadata_parse_mh_full:
2255  * @m: metadata context
2256  * @generic_context: generics context
2257  * @ptr: pointer to the method header.
2258  *
2259  * Decode the method header at @ptr, including pointer to the IL code,
2260  * info about local variables and optional exception tables.
2261  * This is a Mono runtime internal function.
2262  *
2263  * LOCKING: Assumes the loader lock is held.
2264  *
2265  * Returns: a MonoMethodHeader allocated from the image mempool.
2266  */
2267 MonoMethodHeader *
2268 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
2269 {
2270         MonoMethodHeader *mh;
2271         unsigned char flags = *(const unsigned char *) ptr;
2272         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
2273         guint16 fat_flags;
2274         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
2275         const unsigned char *code;
2276         int hsize;
2277         
2278         g_return_val_if_fail (ptr != NULL, NULL);
2279
2280         switch (format) {
2281         case METHOD_HEADER_TINY_FORMAT:
2282                 mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
2283                 ptr++;
2284                 mh->max_stack = 8;
2285                 local_var_sig_tok = 0;
2286                 mh->code_size = flags >> 2;
2287                 mh->code = ptr;
2288                 return mh;
2289         case METHOD_HEADER_TINY_FORMAT1:
2290                 mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
2291                 ptr++;
2292                 mh->max_stack = 8;
2293                 local_var_sig_tok = 0;
2294
2295                 /*
2296                  * The spec claims 3 bits, but the Beta2 is
2297                  * incorrect
2298                  */
2299                 mh->code_size = flags >> 2;
2300                 mh->code = ptr;
2301                 return mh;
2302         case METHOD_HEADER_FAT_FORMAT:
2303                 fat_flags = read16 (ptr);
2304                 ptr += 2;
2305                 hsize = (fat_flags >> 12) & 0xf;
2306                 max_stack = read16 (ptr);
2307                 ptr += 2;
2308                 code_size = read32 (ptr);
2309                 ptr += 4;
2310                 local_var_sig_tok = read32 (ptr);
2311                 ptr += 4;
2312
2313                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
2314                         init_locals = 1;
2315                 else
2316                         init_locals = 0;
2317
2318                 code = ptr;
2319
2320                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
2321                         break;
2322
2323                 /*
2324                  * There are more sections
2325                  */
2326                 ptr = code + code_size;
2327                 break;
2328         default:
2329                 return NULL;
2330         }
2331                        
2332         if (local_var_sig_tok) {
2333                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
2334                 const char *locals_ptr;
2335                 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
2336                 int len=0, i, bsize;
2337
2338                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
2339                 locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
2340                 bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
2341                 if (*locals_ptr != 0x07)
2342                         g_warning ("wrong signature for locals blob");
2343                 locals_ptr++;
2344                 len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
2345                 mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
2346                 mh->num_locals = len;
2347                 for (i = 0; i < len; ++i) {
2348                         mh->locals [i] = mono_metadata_parse_type_full (
2349                                 m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
2350                         if (!mh->locals [i]) {
2351                                 return NULL;
2352                         }
2353                 }
2354         } else {
2355                 mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
2356         }
2357         mh->code = code;
2358         mh->code_size = code_size;
2359         mh->max_stack = max_stack;
2360         mh->init_locals = init_locals;
2361         if (fat_flags & METHOD_HEADER_MORE_SECTS)
2362                 parse_section_data (m, mh, (const unsigned char*)ptr);
2363         return mh;
2364 }
2365
2366 /*
2367  * mono_metadata_parse_mh:
2368  * @generic_context: generics context
2369  * @ptr: pointer to the method header.
2370  *
2371  * Decode the method header at @ptr, including pointer to the IL code,
2372  * info about local variables and optional exception tables.
2373  * This is a Mono runtime internal function.
2374  *
2375  * Returns: a MonoMethodHeader.
2376  */
2377 MonoMethodHeader *
2378 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
2379 {
2380         MonoMethodHeader *res;
2381
2382         mono_loader_lock ();
2383
2384         res = mono_metadata_parse_mh_full (m, NULL, ptr);
2385
2386         mono_loader_unlock ();
2387
2388         return res;
2389 }
2390
2391 /*
2392  * mono_metadata_free_mh:
2393  * @mh: a method header
2394  *
2395  * Free the memory allocated for the method header.
2396  * This is a Mono runtime internal function.
2397  */
2398 void
2399 mono_metadata_free_mh (MonoMethodHeader *mh)
2400 {
2401         /* Allocated from the mempool */
2402 }
2403
2404 /*
2405  * mono_method_header_get_code:
2406  * @header: a MonoMethodHeader pointer
2407  * @code_size: memory location for returning the code size
2408  * @max_stack: memory location for returning the max stack
2409  *
2410  * Method header accessor to retreive info about the IL code properties:
2411  * a pointer to the IL code itself, the size of the code and the max number
2412  * of stack slots used by the code.
2413  *
2414  * Returns: pointer to the IL code represented by the method header.
2415  */
2416 const unsigned char*
2417 mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
2418 {
2419         if (code_size)
2420                 *code_size = header->code_size;
2421         if (max_stack)
2422                 *max_stack = header->max_stack;
2423         return header->code;
2424 }
2425
2426 /*
2427  * mono_method_header_get_locals:
2428  * @header: a MonoMethodHeader pointer
2429  * @num_locals: memory location for returning the number of local variables
2430  * @init_locals: memory location for returning the init_locals flag
2431  *
2432  * Method header accessor to retreive info about the local variables:
2433  * an array of local types, the number of locals and whether the locals
2434  * are supposed to be initialized to 0 on method entry
2435  *
2436  * Returns: pointer to an array of types of the local variables
2437  */
2438 MonoType**
2439 mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
2440 {
2441         if (num_locals)
2442                 *num_locals = header->num_locals;
2443         if (init_locals)
2444                 *init_locals = header->init_locals;
2445         return header->locals;
2446 }
2447
2448 /*
2449  * mono_method_header_get_num_clauses:
2450  * @header: a MonoMethodHeader pointer
2451  *
2452  * Method header accessor to retreive the number of exception clauses.
2453  *
2454  * Returns: the number of exception clauses present
2455  */
2456 int
2457 mono_method_header_get_num_clauses (MonoMethodHeader *header)
2458 {
2459         return header->num_clauses;
2460 }
2461
2462 /*
2463  * mono_method_header_get_clauses:
2464  * @header: a MonoMethodHeader pointer
2465  * @method: MonoMethod the header belongs to
2466  * @iter: pointer to a iterator
2467  * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
2468  *
2469  * Get the info about the exception clauses in the method. Set *iter to NULL to
2470  * initiate the iteration, then call the method repeatedly until it returns FALSE.
2471  * At each iteration, the structure pointed to by clause if filled with the
2472  * exception clause information.
2473  *
2474  * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
2475  * clauses.
2476  */
2477 int
2478 mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
2479 {
2480         MonoExceptionClause *sc;
2481         /* later we'll be able to use this interface to parse the clause info on demand,
2482          * without allocating anything.
2483          */
2484         if (!iter || !header->num_clauses)
2485                 return FALSE;
2486         if (!*iter) {
2487                 *iter = sc = header->clauses;
2488                 *clause = *sc;
2489                 return TRUE;
2490         }
2491         sc = *iter;
2492         sc++;
2493         if (sc < header->clauses + header->num_clauses) {
2494                 *iter = sc;
2495                 *clause = *sc;
2496                 return TRUE;
2497         }
2498         return FALSE;
2499 }
2500
2501 /**
2502  * mono_metadata_parse_field_type:
2503  * @m: metadata context to extract information from
2504  * @ptr: pointer to the field signature
2505  * @rptr: pointer updated to match the end of the decoded stream
2506  *
2507  * Parses the field signature, and returns the type information for it. 
2508  *
2509  * Returns: The MonoType that was extracted from @ptr.
2510  */
2511 MonoType *
2512 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
2513 {
2514         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
2515 }
2516
2517 /**
2518  * mono_metadata_parse_param:
2519  * @m: metadata context to extract information from
2520  * @ptr: pointer to the param signature
2521  * @rptr: pointer updated to match the end of the decoded stream
2522  *
2523  * Parses the param signature, and returns the type information for it. 
2524  *
2525  * Returns: The MonoType that was extracted from @ptr.
2526  */
2527 MonoType *
2528 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
2529 {
2530         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
2531 }
2532
2533 /*
2534  * mono_metadata_token_from_dor:
2535  * @dor_token: A TypeDefOrRef coded index
2536  *
2537  * dor_token is a TypeDefOrRef coded index: it contains either
2538  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
2539  * bits contain an index into the table.
2540  *
2541  * Returns: an expanded token
2542  */
2543 guint32
2544 mono_metadata_token_from_dor (guint32 dor_index)
2545 {
2546         guint32 table, idx;
2547
2548         table = dor_index & 0x03;
2549         idx = dor_index >> 2;
2550
2551         switch (table){
2552         case 0: /* TypeDef */
2553                 return MONO_TOKEN_TYPE_DEF | idx;
2554         case 1: /* TypeRef */
2555                 return MONO_TOKEN_TYPE_REF | idx;
2556         case 2: /* TypeSpec */
2557                 return MONO_TOKEN_TYPE_SPEC | idx;
2558         default:
2559                 g_assert_not_reached ();
2560         }
2561
2562         return 0;
2563 }
2564
2565 /*
2566  * We use this to pass context information to the row locator
2567  */
2568 typedef struct {
2569         int idx;                        /* The index that we are trying to locate */
2570         int col_idx;            /* The index in the row where idx may be stored */
2571         MonoTableInfo *t;       /* pointer to the table */
2572         guint32 result;
2573 } locator_t;
2574
2575 /*
2576  * How the row locator works.
2577  *
2578  *   Table A
2579  *   ___|___
2580  *   ___|___         Table B
2581  *   ___|___------>  _______
2582  *   ___|___         _______
2583  *   
2584  * A column in the rows of table A references an index in table B.
2585  * For example A may be the TYPEDEF table and B the METHODDEF table.
2586  * 
2587  * Given an index in table B we want to get the row in table A
2588  * where the column n references our index in B.
2589  *
2590  * In the locator_t structure:
2591  *      t is table A
2592  *      col_idx is the column number
2593  *      index is the index in table B
2594  *      result will be the index in table A
2595  *
2596  * Examples:
2597  * Table A              Table B         column (in table A)
2598  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
2599  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
2600  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
2601  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
2602  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
2603  *
2604  * Note that we still don't support encoded indexes.
2605  *
2606  */
2607 static int
2608 typedef_locator (const void *a, const void *b)
2609 {
2610         locator_t *loc = (locator_t *) a;
2611         const char *bb = (const char *) b;
2612         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
2613         guint32 col, col_next;
2614
2615         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
2616
2617         if (loc->idx < col)
2618                 return -1;
2619
2620         /*
2621          * Need to check that the next row is valid.
2622          */
2623         if (typedef_index + 1 < loc->t->rows) {
2624                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
2625                 if (loc->idx >= col_next)
2626                         return 1;
2627
2628                 if (col == col_next)
2629                         return 1; 
2630         }
2631
2632         loc->result = typedef_index;
2633         
2634         return 0;
2635 }
2636
2637 static int
2638 table_locator (const void *a, const void *b)
2639 {
2640         locator_t *loc = (locator_t *) a;
2641         const char *bb = (const char *) b;
2642         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
2643         guint32 col;
2644         
2645         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
2646
2647         if (loc->idx == col) {
2648                 loc->result = table_index;
2649                 return 0;
2650         }
2651         if (loc->idx < col)
2652                 return -1;
2653         else 
2654                 return 1;
2655 }
2656
2657 static int
2658 declsec_locator (const void *a, const void *b)
2659 {
2660         locator_t *loc = (locator_t *) a;
2661         const char *bb = (const char *) b;
2662         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
2663         guint32 col;
2664
2665         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
2666
2667         if (loc->idx == col) {
2668                 loc->result = table_index;
2669                 return 0;
2670         }
2671         if (loc->idx < col)
2672                 return -1;
2673         else
2674                 return 1;
2675 }
2676
2677 /**
2678  * mono_metadata_typedef_from_field:
2679  * @meta: metadata context
2680  * @index: FieldDef token
2681  *
2682  * Returns: the 1-based index into the TypeDef table of the type that
2683  * declared the field described by @index, or 0 if not found.
2684  */
2685 guint32
2686 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
2687 {
2688         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
2689         locator_t loc;
2690
2691         if (!tdef->base)
2692                 return 0;
2693
2694         loc.idx = mono_metadata_token_index (index);
2695         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
2696         loc.t = tdef;
2697
2698         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
2699                 g_assert_not_reached ();
2700
2701         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2702         return loc.result + 1;
2703 }
2704
2705 /*
2706  * mono_metadata_typedef_from_method:
2707  * @meta: metadata context
2708  * @index: MethodDef token
2709  *
2710  * Returns: the 1-based index into the TypeDef table of the type that
2711  * declared the method described by @index.  0 if not found.
2712  */
2713 guint32
2714 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
2715 {
2716         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
2717         locator_t loc;
2718         
2719         if (!tdef->base)
2720                 return 0;
2721
2722         loc.idx = mono_metadata_token_index (index);
2723         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
2724         loc.t = tdef;
2725
2726         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
2727                 g_assert_not_reached ();
2728
2729         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2730         return loc.result + 1;
2731 }
2732
2733 /*
2734  * mono_metadata_interfaces_from_typedef_full:
2735  * @meta: metadata context
2736  * @index: typedef token
2737  * 
2738  * The array of interfaces that the @index typedef token implements is returned in
2739  * @interfaces. The number of elemnts in the array is returned in @count.
2740  *
2741  * LOCKING: Assumes the loader lock is held.
2742  *
2743  * Returns: TRUE on success, FALSE on failure.
2744  */
2745 gboolean
2746 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, MonoGenericContext *context)
2747 {
2748         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
2749         locator_t loc;
2750         guint32 start, pos;
2751         guint32 cols [MONO_INTERFACEIMPL_SIZE];
2752         MonoClass **result;
2753
2754         *interfaces = NULL;
2755         *count = 0;
2756
2757         if (!tdef->base)
2758                 return TRUE;
2759
2760         loc.idx = mono_metadata_token_index (index);
2761         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
2762         loc.t = tdef;
2763
2764         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2765                 return TRUE;
2766
2767         start = loc.result;
2768         /*
2769          * We may end up in the middle of the rows... 
2770          */
2771         while (start > 0) {
2772                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
2773                         start--;
2774                 else
2775                         break;
2776         }
2777         pos = start;
2778         while (pos < tdef->rows) {
2779                 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
2780                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
2781                         break;
2782                 ++pos;
2783         }
2784
2785         result = mono_mempool_alloc0 (meta->mempool, sizeof (MonoClass*) * (pos - start));
2786
2787         pos = start;
2788         while (pos < tdef->rows) {
2789                 MonoClass *iface;
2790                 
2791                 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
2792                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
2793                         break;
2794                 iface = mono_class_get_full (
2795                         meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
2796                 if (iface == NULL)
2797                         return FALSE;
2798                 result [pos - start] = iface;
2799                 ++pos;
2800         }
2801         *count = pos - start;
2802         *interfaces = result;
2803         return TRUE;
2804 }
2805
2806 MonoClass**
2807 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
2808 {
2809         MonoClass **interfaces;
2810         gboolean rv;
2811
2812         mono_loader_lock ();
2813         rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL);
2814         mono_loader_unlock ();
2815         if (rv)
2816                 return interfaces;
2817         else
2818                 return NULL;
2819 }
2820
2821 /*
2822  * mono_metadata_nested_in_typedef:
2823  * @meta: metadata context
2824  * @index: typedef token
2825  * 
2826  * Returns: the 1-based index into the TypeDef table of the type
2827  * where the type described by @index is nested.
2828  * Retruns 0 if @index describes a non-nested type.
2829  */
2830 guint32
2831 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
2832 {
2833         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
2834         locator_t loc;
2835         
2836         if (!tdef->base)
2837                 return 0;
2838
2839         loc.idx = mono_metadata_token_index (index);
2840         loc.col_idx = MONO_NESTED_CLASS_NESTED;
2841         loc.t = tdef;
2842
2843         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2844                 return 0;
2845
2846         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2847         return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
2848 }
2849
2850 /*
2851  * mono_metadata_nesting_typedef:
2852  * @meta: metadata context
2853  * @index: typedef token
2854  * 
2855  * Returns: the 1-based index into the TypeDef table of the first type
2856  * that is nested inside the type described by @index. The search starts at
2857  * @start_index.  returns 0 if no such type is found.
2858  */
2859 guint32
2860 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
2861 {
2862         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
2863         guint32 start;
2864         guint32 class_index = mono_metadata_token_index (index);
2865         
2866         if (!tdef->base)
2867                 return 0;
2868
2869         start = start_index;
2870
2871         while (start <= tdef->rows) {
2872                 if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
2873                         break;
2874                 else
2875                         start++;
2876         }
2877
2878         if (start > tdef->rows)
2879                 return 0;
2880         else
2881                 return start;
2882 }
2883
2884 /*
2885  * mono_metadata_packing_from_typedef:
2886  * @meta: metadata context
2887  * @index: token representing a type
2888  * 
2889  * Returns: the info stored in the ClassLAyout table for the given typedef token
2890  * into the @packing and @size pointers.
2891  * Returns 0 if the info is not found.
2892  */
2893 guint32
2894 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
2895 {
2896         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
2897         locator_t loc;
2898         guint32 cols [MONO_CLASS_LAYOUT_SIZE];
2899         
2900         if (!tdef->base)
2901                 return 0;
2902
2903         loc.idx = mono_metadata_token_index (index);
2904         loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
2905         loc.t = tdef;
2906
2907         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2908                 return 0;
2909
2910         mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
2911         if (packing)
2912                 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
2913         if (size)
2914                 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
2915
2916         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2917         return loc.result + 1;
2918 }
2919
2920 /*
2921  * mono_metadata_custom_attrs_from_index:
2922  * @meta: metadata context
2923  * @index: token representing the parent
2924  * 
2925  * Returns: the 1-based index into the CustomAttribute table of the first 
2926  * attribute which belongs to the metadata object described by @index.
2927  * Returns 0 if no such attribute is found.
2928  */
2929 guint32
2930 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
2931 {
2932         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2933         locator_t loc;
2934         
2935         if (!tdef->base)
2936                 return 0;
2937
2938         loc.idx = index;
2939         loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
2940         loc.t = tdef;
2941
2942         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
2943                 return 0;
2944
2945         /* Find the first entry by searching backwards */
2946         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
2947                 loc.result --;
2948
2949         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
2950         return loc.result + 1;
2951 }
2952
2953 /*
2954  * mono_metadata_declsec_from_index:
2955  * @meta: metadata context
2956  * @index: token representing the parent
2957  * 
2958  * Returns: the 0-based index into the DeclarativeSecurity table of the first 
2959  * attribute which belongs to the metadata object described by @index.
2960  * Returns -1 if no such attribute is found.
2961  */
2962 guint32
2963 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
2964 {
2965         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
2966         locator_t loc;
2967
2968         if (!tdef->base)
2969                 return -1;
2970
2971         loc.idx = index;
2972         loc.col_idx = MONO_DECL_SECURITY_PARENT;
2973         loc.t = tdef;
2974
2975         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
2976                 return -1;
2977
2978         /* Find the first entry by searching backwards */
2979         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
2980                 loc.result --;
2981
2982         return loc.result;
2983 }
2984
2985 #ifdef DEBUG
2986 static void
2987 mono_backtrace (int limit)
2988 {
2989         void *array[limit];
2990         char **names;
2991         int i;
2992         backtrace (array, limit);
2993         names = backtrace_symbols (array, limit);
2994         for (i =0; i < limit; ++i) {
2995                 g_print ("\t%s\n", names [i]);
2996         }
2997         g_free (names);
2998 }
2999 #endif
3000
3001 #ifndef __GNUC__
3002 /*#define __alignof__(a) sizeof(a)*/
3003 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
3004 #endif
3005
3006 /*
3007  * mono_type_size:
3008  * @t: the type to return the size of
3009  *
3010  * Returns: the number of bytes required to hold an instance of this
3011  * type in memory
3012  * FIXME: This should really use 'guint32*' for the align parameter.
3013  */
3014 int
3015 mono_type_size (MonoType *t, gint *align)
3016 {
3017         if (!t) {
3018                 *align = 1;
3019                 return 0;
3020         }
3021         if (t->byref) {
3022                 *align = __alignof__(gpointer);
3023                 return sizeof (gpointer);
3024         }
3025
3026         switch (t->type){
3027         case MONO_TYPE_VOID:
3028                 *align = 1;
3029                 return 0;
3030         case MONO_TYPE_BOOLEAN:
3031                 *align = __alignof__(gint8);
3032                 return 1;
3033         case MONO_TYPE_I1:
3034         case MONO_TYPE_U1:
3035                 *align = __alignof__(gint8);
3036                 return 1;
3037         case MONO_TYPE_CHAR:
3038         case MONO_TYPE_I2:
3039         case MONO_TYPE_U2:
3040                 *align = __alignof__(gint16);
3041                 return 2;               
3042         case MONO_TYPE_I4:
3043         case MONO_TYPE_U4:
3044                 *align = __alignof__(gint32);
3045                 return 4;
3046         case MONO_TYPE_R4:
3047                 *align = __alignof__(float);
3048                 return 4;
3049         case MONO_TYPE_I8:
3050         case MONO_TYPE_U8:
3051                 *align = __alignof__(gint64);
3052                 return 8;               
3053         case MONO_TYPE_R8:
3054                 *align = __alignof__(double);
3055                 return 8;               
3056         case MONO_TYPE_I:
3057         case MONO_TYPE_U:
3058                 *align = __alignof__(gpointer);
3059                 return sizeof (gpointer);
3060         case MONO_TYPE_STRING:
3061                 *align = __alignof__(gpointer);
3062                 return sizeof (gpointer);
3063         case MONO_TYPE_OBJECT:
3064                 *align = __alignof__(gpointer);
3065                 return sizeof (gpointer);
3066         case MONO_TYPE_VALUETYPE: {
3067                 if (t->data.klass->enumtype)
3068                         return mono_type_size (t->data.klass->enum_basetype, align);
3069                 else
3070                         return mono_class_value_size (t->data.klass, align);
3071         }
3072         case MONO_TYPE_CLASS:
3073         case MONO_TYPE_SZARRAY:
3074         case MONO_TYPE_PTR:
3075         case MONO_TYPE_FNPTR:
3076         case MONO_TYPE_ARRAY:
3077                 *align = __alignof__(gpointer);
3078                 return sizeof (gpointer);
3079         case MONO_TYPE_TYPEDBYREF:
3080                 return mono_class_value_size (mono_defaults.typed_reference_class, align);
3081         case MONO_TYPE_GENERICINST: {
3082                 MonoInflatedGenericClass *gclass;
3083                 MonoClass *container_class;
3084
3085                 gclass = mono_get_inflated_generic_class (t->data.generic_class);
3086                 // g_assert (!gclass->generic_class.inst->is_open);
3087                 // g_assert (!gclass->klass->generic_container);
3088
3089                 container_class = gclass->generic_class.container_class;
3090
3091                 if (container_class->valuetype) {
3092                         if (container_class->enumtype)
3093                                 return mono_type_size (container_class->enum_basetype, align);
3094                         else
3095                                 return mono_class_value_size (gclass->klass, align);
3096                 } else {
3097                         *align = __alignof__(gpointer);
3098                         return sizeof (gpointer);
3099                 }
3100         }
3101         case MONO_TYPE_VAR:
3102         case MONO_TYPE_MVAR:
3103                 /* FIXME: Martin, this is wrong. */
3104                 *align = __alignof__(gpointer);
3105                 return sizeof (gpointer);
3106         default:
3107                 g_error ("mono_type_size: type 0x%02x unknown", t->type);
3108         }
3109         return 0;
3110 }
3111
3112 /*
3113  * mono_type_stack_size:
3114  * @t: the type to return the size it uses on the stack
3115  *
3116  * Returns: the number of bytes required to hold an instance of this
3117  * type on the runtime stack
3118  * FIXME: This should really use 'guint32*' for the align parameter.
3119  */
3120 int
3121 mono_type_stack_size (MonoType *t, gint *align)
3122 {
3123         int tmp;
3124
3125         g_assert (t != NULL);
3126
3127         if (!align)
3128                 align = &tmp;
3129
3130         if (t->byref) {
3131                 *align = __alignof__(gpointer);
3132                 return sizeof (gpointer);
3133         }
3134
3135         switch (t->type){
3136         case MONO_TYPE_BOOLEAN:
3137         case MONO_TYPE_CHAR:
3138         case MONO_TYPE_I1:
3139         case MONO_TYPE_U1:
3140         case MONO_TYPE_I2:
3141         case MONO_TYPE_U2:
3142         case MONO_TYPE_I4:
3143         case MONO_TYPE_U4:
3144         case MONO_TYPE_I:
3145         case MONO_TYPE_U:
3146         case MONO_TYPE_STRING:
3147         case MONO_TYPE_OBJECT:
3148         case MONO_TYPE_CLASS:
3149         case MONO_TYPE_SZARRAY:
3150         case MONO_TYPE_PTR:
3151         case MONO_TYPE_FNPTR:
3152         case MONO_TYPE_ARRAY:
3153                 *align = __alignof__(gpointer);
3154                 return sizeof (gpointer);
3155         case MONO_TYPE_TYPEDBYREF:
3156                 *align = __alignof__(gpointer);
3157                 return sizeof (gpointer) * 3;
3158         case MONO_TYPE_R4:
3159                 *align = __alignof__(float);
3160                 return sizeof (float);          
3161         case MONO_TYPE_I8:
3162         case MONO_TYPE_U8:
3163                 *align = __alignof__(gint64);
3164                 return sizeof (gint64);         
3165         case MONO_TYPE_R8:
3166                 *align = __alignof__(double);
3167                 return sizeof (double);
3168         case MONO_TYPE_VALUETYPE: {
3169                 guint32 size;
3170
3171                 if (t->data.klass->enumtype)
3172                         return mono_type_stack_size (t->data.klass->enum_basetype, align);
3173                 else {
3174                         size = mono_class_value_size (t->data.klass, align);
3175
3176                         *align = *align + __alignof__(gpointer) - 1;
3177                         *align &= ~(__alignof__(gpointer) - 1);
3178
3179                         size += sizeof (gpointer) - 1;
3180                         size &= ~(sizeof (gpointer) - 1);
3181
3182                         return size;
3183                 }
3184         }
3185         case MONO_TYPE_GENERICINST: {
3186                 MonoInflatedGenericClass *gclass;
3187                 MonoClass *container_class;
3188
3189                 gclass = mono_get_inflated_generic_class (t->data.generic_class);
3190                 container_class = gclass->generic_class.container_class;
3191
3192                 g_assert (!gclass->generic_class.inst->is_open);
3193                 g_assert (!gclass->klass->generic_container);
3194
3195                 if (container_class->valuetype) {
3196                         if (container_class->enumtype)
3197                                 return mono_type_stack_size (container_class->enum_basetype, align);
3198                         else {
3199                                 guint32 size = mono_class_value_size (gclass->klass, align);
3200
3201                                 *align = *align + __alignof__(gpointer) - 1;
3202                                 *align &= ~(__alignof__(gpointer) - 1);
3203
3204                                 size += sizeof (gpointer) - 1;
3205                                 size &= ~(sizeof (gpointer) - 1);
3206
3207                                 return size;
3208                         }
3209                 } else {
3210                         *align = __alignof__(gpointer);
3211                         return sizeof (gpointer);
3212                 }
3213         }
3214         default:
3215                 g_error ("type 0x%02x unknown", t->type);
3216         }
3217         return 0;
3218 }
3219
3220 gboolean
3221 mono_type_generic_inst_is_valuetype (MonoType *type)
3222 {
3223         g_assert (type->type == MONO_TYPE_GENERICINST);
3224         return type->data.generic_class->container_class->valuetype;
3225 }
3226
3227 gboolean
3228 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
3229 {
3230         return gclass->container_class->valuetype;
3231 }
3232
3233 static gboolean
3234 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
3235 {
3236         int i;
3237
3238         if ((g1->inst->type_argc != g2->inst->type_argc) || (g1->is_dynamic != g2->is_dynamic) ||
3239             (g1->inst->is_reference != g2->inst->is_reference))
3240                 return FALSE;
3241         if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
3242                 return FALSE;
3243         for (i = 0; i < g1->inst->type_argc; ++i) {
3244                 if (!do_mono_metadata_type_equal (g1->inst->type_argv [i], g2->inst->type_argv [i], signature_only))
3245                         return FALSE;
3246         }
3247         return TRUE;
3248 }
3249
3250 guint
3251 mono_metadata_generic_method_hash (MonoGenericMethod *gmethod)
3252 {
3253         return gmethod->inst->id;
3254 }
3255
3256 gboolean
3257 mono_metadata_generic_method_equal (MonoGenericMethod *g1, MonoGenericMethod *g2)
3258 {
3259         return (g1->container == g2->container) && (g1->generic_class == g2->generic_class) &&
3260                 (g1->inst == g2->inst);
3261 }
3262
3263
3264 /*
3265  * mono_metadata_type_hash:
3266  * @t1: a type
3267  *
3268  * Computes an hash value for @t1 to be used in GHashTable.
3269  */
3270 guint
3271 mono_metadata_type_hash (MonoType *t1)
3272 {
3273         guint hash = t1->type;
3274
3275         hash |= t1->byref << 6; /* do not collide with t1->type values */
3276         switch (t1->type) {
3277         case MONO_TYPE_VALUETYPE:
3278         case MONO_TYPE_CLASS:
3279         case MONO_TYPE_SZARRAY:
3280                 /* check if the distribution is good enough */
3281                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3282         case MONO_TYPE_PTR:
3283                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
3284         case MONO_TYPE_ARRAY:
3285                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
3286         case MONO_TYPE_GENERICINST:
3287                 return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
3288         }
3289         return hash;
3290 }
3291
3292 static gboolean
3293 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
3294 {
3295         if (p1 == p2)
3296                 return TRUE;
3297         if (p1->num != p2->num)
3298                 return FALSE;
3299
3300         if (p1->owner == p2->owner)
3301                 return TRUE;
3302
3303         /*
3304          * If `signature_only' is true, we're comparing two (method) signatures.
3305          * In this case, the owner of two type parameters doesn't need to match.
3306          */
3307
3308         return signature_only;
3309 }
3310
3311 static gboolean
3312 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
3313 {
3314         if (c1 == c2)
3315                 return TRUE;
3316         if (c1->generic_class && c2->generic_class)
3317                 return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
3318         if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
3319                 return mono_metadata_generic_param_equal (
3320                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
3321         if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
3322                 return mono_metadata_generic_param_equal (
3323                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
3324         if (signature_only &&
3325             (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
3326                 return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
3327         return FALSE;
3328 }
3329
3330 static gboolean
3331 mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
3332 {
3333         gpointer iter1 = 0, iter2 = 0;
3334
3335         if (s1 == s2)
3336                 return TRUE;
3337         if (s1->call_convention != s2->call_convention)
3338                 return FALSE;
3339         if (s1->sentinelpos != s2->sentinelpos)
3340                 return FALSE;
3341         if (s1->hasthis != s2->hasthis)
3342                 return FALSE;
3343         if (s1->explicit_this != s2->explicit_this)
3344                 return FALSE;
3345         if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
3346                 return FALSE;
3347         if (s1->param_count != s2->param_count)
3348                 return FALSE;
3349
3350         while (TRUE) {
3351                 MonoType *t1 = mono_signature_get_params (s1, &iter1);
3352                 MonoType *t2 = mono_signature_get_params (s2, &iter2);
3353
3354                 if (t1 == NULL || t2 == NULL)
3355                         return (t1 == t2);
3356                 if (! do_mono_metadata_type_equal (t1, t2, signature_only))
3357                         return FALSE;
3358         }
3359 }
3360
3361 /*
3362  * mono_metadata_type_equal:
3363  * @t1: a type
3364  * @t2: another type
3365  *
3366  * Determine if @t1 and @t2 represent the same type.
3367  * Returns: #TRUE if @t1 and @t2 are equal.
3368  */
3369 static gboolean
3370 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
3371 {
3372         if (t1->type != t2->type || t1->byref != t2->byref)
3373                 return FALSE;
3374
3375         switch (t1->type) {
3376         case MONO_TYPE_VOID:
3377         case MONO_TYPE_BOOLEAN:
3378         case MONO_TYPE_CHAR:
3379         case MONO_TYPE_I1:
3380         case MONO_TYPE_U1:
3381         case MONO_TYPE_I2:
3382         case MONO_TYPE_U2:
3383         case MONO_TYPE_I4:
3384         case MONO_TYPE_U4:
3385         case MONO_TYPE_I8:
3386         case MONO_TYPE_U8:
3387         case MONO_TYPE_R4:
3388         case MONO_TYPE_R8:
3389         case MONO_TYPE_STRING:
3390         case MONO_TYPE_I:
3391         case MONO_TYPE_U:
3392         case MONO_TYPE_OBJECT:
3393         case MONO_TYPE_TYPEDBYREF:
3394                 return TRUE;
3395         case MONO_TYPE_VALUETYPE:
3396         case MONO_TYPE_CLASS:
3397         case MONO_TYPE_SZARRAY:
3398                 return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
3399         case MONO_TYPE_PTR:
3400                 return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
3401         case MONO_TYPE_ARRAY:
3402                 if (t1->data.array->rank != t2->data.array->rank)
3403                         return FALSE;
3404                 return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
3405         case MONO_TYPE_GENERICINST:
3406                 return _mono_metadata_generic_class_equal (
3407                         t1->data.generic_class, t2->data.generic_class, signature_only);
3408         case MONO_TYPE_VAR:
3409                 return mono_metadata_generic_param_equal (
3410                         t1->data.generic_param, t2->data.generic_param, signature_only);
3411         case MONO_TYPE_MVAR:
3412                 return mono_metadata_generic_param_equal (
3413                         t1->data.generic_param, t2->data.generic_param, signature_only);
3414         case MONO_TYPE_FNPTR:
3415                 return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
3416         default:
3417                 g_error ("implement type compare for %0x!", t1->type);
3418                 return FALSE;
3419         }
3420
3421         return FALSE;
3422 }
3423
3424 gboolean
3425 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
3426 {
3427         return do_mono_metadata_type_equal (t1, t2, FALSE);
3428 }
3429
3430 /**
3431  * mono_metadata_signature_equal:
3432  * @sig1: a signature
3433  * @sig2: another signature
3434  *
3435  * Determine if @sig1 and @sig2 represent the same signature, with the
3436  * same number of arguments and the same types.
3437  * Returns: #TRUE if @sig1 and @sig2 are equal.
3438  */
3439 gboolean
3440 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
3441 {
3442         int i;
3443
3444         if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
3445                 return FALSE;
3446
3447         /*
3448          * We're just comparing the signatures of two methods here:
3449          *
3450          * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
3451          * U and V are equal here.
3452          *
3453          * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
3454          */
3455
3456         for (i = 0; i < sig1->param_count; i++) { 
3457                 MonoType *p1 = sig1->params[i];
3458                 MonoType *p2 = sig2->params[i];
3459                 
3460                 /* if (p1->attrs != p2->attrs)
3461                         return FALSE;
3462                 */
3463                 if (!do_mono_metadata_type_equal (p1, p2, TRUE))
3464                         return FALSE;
3465         }
3466
3467         if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
3468                 return FALSE;
3469         return TRUE;
3470 }
3471
3472 /**
3473  * mono_metadata_type_dup_mp:
3474  * @image: image type is defined in
3475  * @original: type to duplicate
3476  *
3477  * Returns: copy of type allocated from mempool.
3478  */
3479 MonoType *
3480 mono_metadata_type_dup_mp (MonoImage *image, const MonoType *original)
3481 {
3482         MonoType *r = NULL;
3483         mono_loader_lock ();
3484         r = mono_mempool_alloc0 (image->mempool, sizeof(MonoType));
3485         mono_loader_unlock ();
3486         *r = *original;
3487         /* FIXME: we don't handle these yet because they need to duplicate memory
3488          * but the current routines used are not using the mempools
3489          */
3490         if (original->type == MONO_TYPE_PTR || 
3491                 original->type == MONO_TYPE_ARRAY || 
3492                 original->type == MONO_TYPE_FNPTR)
3493                 g_assert_not_reached ();
3494         return r;
3495 }
3496
3497 guint
3498 mono_signature_hash (MonoMethodSignature *sig)
3499 {
3500         guint i, res = sig->ret->type;
3501
3502         for (i = 0; i < sig->param_count; i++)
3503                 res = (res << 5) - res + mono_type_hash (sig->params[i]);
3504
3505         return res;
3506 }
3507
3508 /*
3509  * mono_metadata_encode_value:
3510  * @value: value to encode
3511  * @buf: buffer where to write the compressed representation
3512  * @endbuf: pointer updated to point at the end of the encoded output
3513  *
3514  * Encodes the value @value in the compressed representation used
3515  * in metadata and stores the result in @buf. @buf needs to be big
3516  * enough to hold the data (4 bytes).
3517  */
3518 void
3519 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
3520 {
3521         char *p = buf;
3522         
3523         if (value < 0x80)
3524                 *p++ = value;
3525         else if (value < 0x4000) {
3526                 p [0] = 0x80 | (value >> 8);
3527                 p [1] = value & 0xff;
3528                 p += 2;
3529         } else {
3530                 p [0] = (value >> 24) | 0xc0;
3531                 p [1] = (value >> 16) & 0xff;
3532                 p [2] = (value >> 8) & 0xff;
3533                 p [3] = value & 0xff;
3534                 p += 4;
3535         }
3536         if (endbuf)
3537                 *endbuf = p;
3538 }
3539
3540 /*
3541  * mono_metadata_field_info:
3542  * @meta: the Image the field is defined in
3543  * @index: the index in the field table representing the field
3544  * @offset: a pointer to an integer where to store the offset that 
3545  * may have been specified for the field in a FieldLayout table
3546  * @rva: a pointer to the RVA of the field data in the image that
3547  * may have been defined in a FieldRVA table
3548  * @marshal_spec: a pointer to the marshal spec that may have been 
3549  * defined for the field in a FieldMarshal table.
3550  *
3551  * Gather info for field @index that may have been defined in the FieldLayout, 
3552  * FieldRVA and FieldMarshal tables.
3553  * Either of offset, rva and marshal_spec can be NULL if you're not interested 
3554  * in the data.
3555  */
3556 void
3557 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
3558                           MonoMarshalSpec **marshal_spec)
3559 {
3560         MonoTableInfo *tdef;
3561         locator_t loc;
3562
3563         loc.idx = index + 1;
3564         if (offset) {
3565                 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
3566
3567                 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
3568                 loc.t = tdef;
3569
3570                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
3571                         *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
3572                 } else {
3573                         *offset = (guint32)-1;
3574                 }
3575         }
3576         if (rva) {
3577                 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
3578
3579                 loc.col_idx = MONO_FIELD_RVA_FIELD;
3580                 loc.t = tdef;
3581                 
3582                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
3583                         /*
3584                          * LAMESPEC: There is no signature, no nothing, just the raw data.
3585                          */
3586                         *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
3587                 } else {
3588                         *rva = 0;
3589                 }
3590         }
3591         if (marshal_spec) {
3592                 const char *p;
3593                 
3594                 if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
3595                         *marshal_spec = mono_metadata_parse_marshal_spec (meta, p);
3596                 }
3597         }
3598
3599 }
3600
3601 /*
3602  * mono_metadata_get_constant_index:
3603  * @meta: the Image the field is defined in
3604  * @index: the token that may have a row defined in the constants table
3605  * @hint: possible position for the row
3606  *
3607  * @token must be a FieldDef, ParamDef or PropertyDef token.
3608  *
3609  * Returns: the index into the Constants table or 0 if not found.
3610  */
3611 guint32
3612 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
3613 {
3614         MonoTableInfo *tdef;
3615         locator_t loc;
3616         guint32 index = mono_metadata_token_index (token);
3617
3618         tdef = &meta->tables [MONO_TABLE_CONSTANT];
3619         index <<= MONO_HASCONSTANT_BITS;
3620         switch (mono_metadata_token_table (token)) {
3621         case MONO_TABLE_FIELD:
3622                 index |= MONO_HASCONSTANT_FIEDDEF;
3623                 break;
3624         case MONO_TABLE_PARAM:
3625                 index |= MONO_HASCONSTANT_PARAM;
3626                 break;
3627         case MONO_TABLE_PROPERTY:
3628                 index |= MONO_HASCONSTANT_PROPERTY;
3629                 break;
3630         default:
3631                 g_warning ("Not a valid token for the constant table: 0x%08x", token);
3632                 return 0;
3633         }
3634         loc.idx = index;
3635         loc.col_idx = MONO_CONSTANT_PARENT;
3636         loc.t = tdef;
3637
3638         if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
3639                 return hint;
3640
3641         if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
3642                 return loc.result + 1;
3643         }
3644         return 0;
3645 }
3646
3647 /*
3648  * mono_metadata_events_from_typedef:
3649  * @meta: metadata context
3650  * @index: 0-based index (in the TypeDef table) describing a type
3651  *
3652  * Returns: the 0-based index in the Event table for the events in the
3653  * type. The last event that belongs to the type (plus 1) is stored
3654  * in the @end_idx pointer.
3655  */
3656 guint32
3657 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
3658 {
3659         locator_t loc;
3660         guint32 start, end;
3661         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_EVENTMAP];
3662
3663         *end_idx = 0;
3664         
3665         if (!tdef->base)
3666                 return 0;
3667
3668         loc.t = tdef;
3669         loc.col_idx = MONO_EVENT_MAP_PARENT;
3670         loc.idx = index + 1;
3671
3672         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3673                 return 0;
3674         
3675         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
3676         if (loc.result + 1 < tdef->rows) {
3677                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
3678         } else {
3679                 end = meta->tables [MONO_TABLE_EVENT].rows;
3680         }
3681
3682         *end_idx = end;
3683         return start - 1;
3684 }
3685
3686 /*
3687  * mono_metadata_methods_from_event:
3688  * @meta: metadata context
3689  * @index: 0-based index (in the Event table) describing a event
3690  *
3691  * Returns: the 0-based index in the MethodDef table for the methods in the
3692  * event. The last method that belongs to the event (plus 1) is stored
3693  * in the @end_idx pointer.
3694  */
3695 guint32
3696 mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_idx)
3697 {
3698         locator_t loc;
3699         guint start, end;
3700         guint32 cols [MONO_METHOD_SEMA_SIZE];
3701         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
3702
3703         *end_idx = 0;
3704         if (!msemt->base)
3705                 return 0;
3706
3707         loc.t = msemt;
3708         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
3709         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
3710
3711         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
3712                 return 0;
3713
3714         start = loc.result;
3715         /*
3716          * We may end up in the middle of the rows... 
3717          */
3718         while (start > 0) {
3719                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
3720                         start--;
3721                 else
3722                         break;
3723         }
3724         end = start + 1;
3725         while (end < msemt->rows) {
3726                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
3727                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
3728                         break;
3729                 ++end;
3730         }
3731         *end_idx = end;
3732         return start;
3733 }
3734
3735 /*
3736  * mono_metadata_properties_from_typedef:
3737  * @meta: metadata context
3738  * @index: 0-based index (in the TypeDef table) describing a type
3739  *
3740  * Returns: the 0-based index in the Property table for the properties in the
3741  * type. The last property that belongs to the type (plus 1) is stored
3742  * in the @end_idx pointer.
3743  */
3744 guint32
3745 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
3746 {
3747         locator_t loc;
3748         guint32 start, end;
3749         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_PROPERTYMAP];
3750
3751         *end_idx = 0;
3752         
3753         if (!tdef->base)
3754                 return 0;
3755
3756         loc.t = tdef;
3757         loc.col_idx = MONO_PROPERTY_MAP_PARENT;
3758         loc.idx = index + 1;
3759
3760         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3761                 return 0;
3762         
3763         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
3764         if (loc.result + 1 < tdef->rows) {
3765                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
3766         } else {
3767                 end = meta->tables [MONO_TABLE_PROPERTY].rows;
3768         }
3769
3770         *end_idx = end;
3771         return start - 1;
3772 }
3773
3774 /*
3775  * mono_metadata_methods_from_property:
3776  * @meta: metadata context
3777  * @index: 0-based index (in the PropertyDef table) describing a property
3778  *
3779  * Returns: the 0-based index in the MethodDef table for the methods in the
3780  * property. The last method that belongs to the property (plus 1) is stored
3781  * in the @end_idx pointer.
3782  */
3783 guint32
3784 mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *end_idx)
3785 {
3786         locator_t loc;
3787         guint start, end;
3788         guint32 cols [MONO_METHOD_SEMA_SIZE];
3789         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
3790
3791         *end_idx = 0;
3792         if (!msemt->base)
3793                 return 0;
3794
3795         loc.t = msemt;
3796         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
3797         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
3798
3799         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
3800                 return 0;
3801
3802         start = loc.result;
3803         /*
3804          * We may end up in the middle of the rows... 
3805          */
3806         while (start > 0) {
3807                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
3808                         start--;
3809                 else
3810                         break;
3811         }
3812         end = start + 1;
3813         while (end < msemt->rows) {
3814                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
3815                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
3816                         break;
3817                 ++end;
3818         }
3819         *end_idx = end;
3820         return start;
3821 }
3822
3823 guint32
3824 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
3825 {
3826         locator_t loc;
3827         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_IMPLMAP];
3828
3829         if (!tdef->base)
3830                 return 0;
3831
3832         loc.t = tdef;
3833         loc.col_idx = MONO_IMPLMAP_MEMBER;
3834         loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
3835
3836         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3837                 return 0;
3838
3839         return loc.result + 1;
3840 }
3841
3842 /**
3843  * @image: context where the image is created
3844  * @type_spec:  typespec token
3845  *
3846  * Creates a MonoType representing the TypeSpec indexed by the @type_spec
3847  * token.
3848  */
3849 MonoType *
3850 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
3851 {
3852         guint32 idx = mono_metadata_token_index (type_spec);
3853         MonoTableInfo *t;
3854         guint32 cols [MONO_TYPESPEC_SIZE];
3855         const char *ptr;
3856         guint32 len;
3857         MonoType *type;
3858
3859         mono_loader_lock ();
3860
3861         type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
3862         if (type) {
3863                 mono_loader_unlock ();
3864                 return type;
3865         }
3866
3867         t = &image->tables [MONO_TABLE_TYPESPEC];
3868
3869         mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
3870         ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
3871         len = mono_metadata_decode_value (ptr, &ptr);
3872
3873         type = g_new0 (MonoType, 1);
3874
3875         g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
3876
3877         if (*ptr == MONO_TYPE_BYREF) {
3878                 type->byref = 1;
3879                 ptr++;
3880         }
3881
3882         if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) {
3883                 g_hash_table_remove (image->typespec_cache, GUINT_TO_POINTER (type_spec));
3884                 g_free (type);
3885                 mono_loader_unlock ();
3886                 return NULL;
3887         }
3888
3889         mono_loader_unlock ();
3890
3891         return type;
3892 }
3893
3894 MonoMarshalSpec *
3895 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
3896 {
3897         MonoMarshalSpec *res;
3898         int len;
3899         const char *start = ptr;
3900
3901         /* fixme: this is incomplete, but I cant find more infos in the specs */
3902
3903         res = g_new0 (MonoMarshalSpec, 1);
3904         
3905         len = mono_metadata_decode_value (ptr, &ptr);
3906         res->native = *ptr++;
3907
3908         if (res->native == MONO_NATIVE_LPARRAY) {
3909                 res->data.array_data.param_num = -1;
3910                 res->data.array_data.num_elem = -1;
3911                 res->data.array_data.elem_mult = -1;
3912
3913                 if (ptr - start <= len)
3914                         res->data.array_data.elem_type = *ptr++;
3915                 if (ptr - start <= len)
3916                         res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
3917                 if (ptr - start <= len)
3918                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
3919                 if (ptr - start <= len) {
3920                         /*
3921                          * LAMESPEC: Older spec versions say this parameter comes before 
3922                          * num_elem. Never spec versions don't talk about elem_mult at
3923                          * all, but csc still emits it, and it is used to distinguish
3924                          * between param_num being 0, and param_num being omitted.
3925                          * So if (param_num == 0) && (num_elem > 0), then
3926                          * elem_mult == 0 -> the array size is num_elem
3927                          * elem_mult == 1 -> the array size is @param_num + num_elem
3928                          */
3929                         res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
3930                 }
3931         } 
3932
3933         if (res->native == MONO_NATIVE_BYVALTSTR) {
3934                 if (ptr - start <= len)
3935                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
3936         }
3937
3938         if (res->native == MONO_NATIVE_BYVALARRAY) {
3939                 if (ptr - start <= len)
3940                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
3941         }
3942         
3943         if (res->native == MONO_NATIVE_CUSTOM) {
3944                 /* skip unused type guid */
3945                 len = mono_metadata_decode_value (ptr, &ptr);
3946                 ptr += len;
3947                 /* skip unused native type name */
3948                 len = mono_metadata_decode_value (ptr, &ptr);
3949                 ptr += len;
3950                 /* read custom marshaler type name */
3951                 len = mono_metadata_decode_value (ptr, &ptr);
3952                 res->data.custom_data.custom_name = g_strndup (ptr, len);               
3953                 ptr += len;
3954                 /* read cookie string */
3955                 len = mono_metadata_decode_value (ptr, &ptr);
3956                 res->data.custom_data.cookie = g_strndup (ptr, len);
3957         }
3958
3959         if (res->native == MONO_NATIVE_SAFEARRAY) {
3960                 res->data.safearray_data.elem_type = 0;
3961                 res->data.safearray_data.num_elem = 0;
3962                 if (ptr - start <= len)
3963                         res->data.safearray_data.elem_type = *ptr++;
3964                 if (ptr - start <= len)
3965                         res->data.safearray_data.num_elem = *ptr++;
3966         }
3967         return res;
3968 }
3969
3970 void 
3971 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
3972 {
3973         if (spec->native == MONO_NATIVE_CUSTOM) {
3974                 g_free (spec->data.custom_data.custom_name);
3975                 g_free (spec->data.custom_data.cookie);
3976         }
3977         g_free (spec);
3978 }
3979         
3980 guint32
3981 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
3982                         gboolean unicode, MonoMarshalConv *conv) 
3983 {
3984         MonoMarshalConv dummy_conv;
3985         int t = type->type;
3986
3987         if (!conv)
3988                 conv = &dummy_conv;
3989
3990         *conv = MONO_MARSHAL_CONV_NONE;
3991
3992         if (type->byref)
3993                 return MONO_NATIVE_UINT;
3994
3995 handle_enum:
3996         switch (t) {
3997         case MONO_TYPE_BOOLEAN: 
3998                 if (mspec) {
3999                         switch (mspec->native) {
4000                         case MONO_NATIVE_VARIANTBOOL:
4001                                 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
4002                                 return MONO_NATIVE_VARIANTBOOL;
4003                         case MONO_NATIVE_BOOLEAN:
4004                                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
4005                                 return MONO_NATIVE_BOOLEAN;
4006                         case MONO_NATIVE_I1:
4007                         case MONO_NATIVE_U1:
4008                                 return mspec->native;
4009                         default:
4010                                 g_error ("cant marshal bool to native type %02x", mspec->native);
4011                         }
4012                 }
4013                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
4014                 return MONO_NATIVE_BOOLEAN;
4015         case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
4016         case MONO_TYPE_I1: return MONO_NATIVE_I1;
4017         case MONO_TYPE_U1: return MONO_NATIVE_U1;
4018         case MONO_TYPE_I2: return MONO_NATIVE_I2;
4019         case MONO_TYPE_U2: return MONO_NATIVE_U2;
4020         case MONO_TYPE_I4: return MONO_NATIVE_I4;
4021         case MONO_TYPE_U4: return MONO_NATIVE_U4;
4022         case MONO_TYPE_I8: return MONO_NATIVE_I8;
4023         case MONO_TYPE_U8: return MONO_NATIVE_U8;
4024         case MONO_TYPE_R4: return MONO_NATIVE_R4;
4025         case MONO_TYPE_R8: return MONO_NATIVE_R8;
4026         case MONO_TYPE_STRING:
4027                 if (mspec) {
4028                         switch (mspec->native) {
4029                         case MONO_NATIVE_BSTR:
4030                                 *conv = MONO_MARSHAL_CONV_STR_BSTR;
4031                                 return MONO_NATIVE_BSTR;
4032                         case MONO_NATIVE_LPSTR:
4033                                 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
4034                                 return MONO_NATIVE_LPSTR;
4035                         case MONO_NATIVE_LPWSTR:
4036                                 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
4037                                 return MONO_NATIVE_LPWSTR;
4038                         case MONO_NATIVE_LPTSTR:
4039                                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
4040                                 return MONO_NATIVE_LPTSTR;
4041                         case MONO_NATIVE_ANSIBSTR:
4042                                 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
4043                                 return MONO_NATIVE_ANSIBSTR;
4044                         case MONO_NATIVE_TBSTR:
4045                                 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
4046                                 return MONO_NATIVE_TBSTR;
4047                         case MONO_NATIVE_BYVALTSTR:
4048                                 if (unicode)
4049                                         *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
4050                                 else
4051                                         *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
4052                                 return MONO_NATIVE_BYVALTSTR;
4053                         default:
4054                                 g_error ("Can not marshal string to native type '%02x': Invalid managed/unmanaged type combination (String fields must be paired with LPStr, LPWStr, BStr or ByValTStr).", mspec->native);
4055                         }
4056                 }       
4057                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
4058                 return MONO_NATIVE_LPTSTR; 
4059         case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
4060         case MONO_TYPE_VALUETYPE: /*FIXME*/
4061                 if (type->data.klass->enumtype) {
4062                         t = type->data.klass->enum_basetype->type;
4063                         goto handle_enum;
4064                 }
4065                 return MONO_NATIVE_STRUCT;
4066         case MONO_TYPE_SZARRAY: 
4067         case MONO_TYPE_ARRAY: 
4068                 if (mspec) {
4069                         switch (mspec->native) {
4070                         case MONO_NATIVE_BYVALARRAY:
4071                                 if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
4072                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
4073                                 else
4074                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
4075                                 return MONO_NATIVE_BYVALARRAY;
4076                         case MONO_NATIVE_SAFEARRAY:
4077                                 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
4078                                 return MONO_NATIVE_SAFEARRAY;
4079                         case MONO_NATIVE_LPARRAY:                               
4080                                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
4081                                 return MONO_NATIVE_LPARRAY;
4082                         default:
4083                                 g_error ("cant marshal array as native type %02x", mspec->native);
4084                         }
4085                 }       
4086
4087                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
4088                 return MONO_NATIVE_LPARRAY;
4089         case MONO_TYPE_I: return MONO_NATIVE_INT;
4090         case MONO_TYPE_U: return MONO_NATIVE_UINT;
4091         case MONO_TYPE_CLASS: 
4092         case MONO_TYPE_OBJECT: {
4093                 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
4094                 if (mspec) {
4095                         switch (mspec->native) {
4096                         case MONO_NATIVE_STRUCT:
4097                                 return MONO_NATIVE_STRUCT;
4098                         case MONO_NATIVE_INTERFACE:
4099                                 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
4100                                 return MONO_NATIVE_INTERFACE;
4101                         case MONO_NATIVE_IDISPATCH:
4102                                 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
4103                                 return MONO_NATIVE_IDISPATCH;
4104                         case MONO_NATIVE_IUNKNOWN:
4105                                 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
4106                                 return MONO_NATIVE_IUNKNOWN;
4107                         case MONO_NATIVE_FUNC:
4108                                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
4109                                                                                          type->data.klass == mono_defaults.delegate_class || 
4110                                                                                          type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
4111                                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
4112                                         return MONO_NATIVE_FUNC;
4113                                 }
4114                                 /* Fall through */
4115                         default:
4116                                 g_error ("cant marshal object as native type %02x", mspec->native);
4117                         }
4118                 }
4119                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
4120                                              type->data.klass == mono_defaults.delegate_class || 
4121                                              type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
4122                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
4123                         return MONO_NATIVE_FUNC;
4124                 }
4125                 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
4126                 return MONO_NATIVE_STRUCT;
4127         }
4128         case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
4129         case MONO_TYPE_GENERICINST:
4130                 type = &type->data.generic_class->container_class->byval_arg;
4131                 t = type->type;
4132                 goto handle_enum;
4133         case MONO_TYPE_TYPEDBYREF:
4134         default:
4135                 g_error ("type 0x%02x not handled in marshal", t);
4136         }
4137         return MONO_NATIVE_MAX;
4138 }
4139
4140 const char*
4141 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
4142 {
4143         locator_t loc;
4144         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_FIELDMARSHAL];
4145
4146         if (!tdef->base)
4147                 return NULL;
4148
4149         loc.t = tdef;
4150         loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
4151         loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
4152
4153         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4154                 return NULL;
4155
4156         return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
4157 }
4158
4159 static MonoMethod*
4160 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
4161 {
4162         guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
4163         switch (tok & MONO_METHODDEFORREF_MASK) {
4164         case MONO_METHODDEFORREF_METHODDEF:
4165                 return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
4166         case MONO_METHODDEFORREF_METHODREF:
4167                 return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
4168         }
4169         g_assert_not_reached ();
4170         return NULL;
4171 }
4172
4173 /*
4174  * mono_class_get_overrides_full:
4175  *
4176  *   Return the method overrides belonging to class @type_token in @overrides, and
4177  * the number of overrides in @num_overrides.
4178  *
4179  * Returns: TRUE on success, FALSE on failure.
4180  */
4181 gboolean
4182 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
4183                                MonoGenericContext *generic_context)
4184 {
4185         locator_t loc;
4186         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
4187         guint32 start, end;
4188         gint32 i, num;
4189         guint32 cols [MONO_METHODIMPL_SIZE];
4190         MonoMethod **result;
4191         gint32 ok = TRUE;
4192         
4193         *overrides = NULL;
4194         if (num_overrides)
4195                 *num_overrides = 0;
4196
4197         if (!tdef->base)
4198                 return TRUE;
4199
4200         loc.t = tdef;
4201         loc.col_idx = MONO_METHODIMPL_CLASS;
4202         loc.idx = mono_metadata_token_index (type_token);
4203
4204         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4205                 return TRUE;
4206
4207         start = loc.result;
4208         end = start + 1;
4209         /*
4210          * We may end up in the middle of the rows... 
4211          */
4212         while (start > 0) {
4213                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
4214                         start--;
4215                 else
4216                         break;
4217         }
4218         while (end < tdef->rows) {
4219                 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
4220                         end++;
4221                 else
4222                         break;
4223         }
4224         num = end - start;
4225         result = g_new (MonoMethod*, num * 2);
4226         for (i = 0; i < num; ++i) {
4227                 MonoMethod *method;
4228
4229                 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
4230                 method = method_from_method_def_or_ref (
4231                         image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
4232                 if (method == NULL)
4233                         ok = FALSE;
4234                 result [i * 2] = method;
4235                 method = method_from_method_def_or_ref (
4236                         image, cols [MONO_METHODIMPL_BODY], generic_context);
4237                 if (method == NULL)
4238                         ok = FALSE;
4239                 result [i * 2 + 1] = method;
4240         }
4241
4242         *overrides = result;
4243         if (num_overrides)
4244                 *num_overrides = num;
4245         return ok;
4246 }
4247
4248 /**
4249  * mono_guid_to_string:
4250  *
4251  * Converts a 16 byte Microsoft GUID to the standard string representation.
4252  */
4253 char *
4254 mono_guid_to_string (const guint8 *guid)
4255 {
4256         return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
4257                                 guid[3], guid[2], guid[1], guid[0],
4258                                 guid[5], guid[4],
4259                                 guid[7], guid[6],
4260                                 guid[8], guid[9],
4261                                 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
4262 }
4263
4264 static gboolean
4265 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
4266 {
4267         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
4268         guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
4269         guint32 i, token, found;
4270         MonoClass *klass, **res;
4271         GList *cons = NULL, *tmp;
4272         MonoGenericContext *context = &container->context;
4273
4274         /* FIXME: !container->klass => this is probably monodis */
4275         g_assert (!container->klass || context->gclass || context->gmethod);
4276
4277         *constraints = NULL;
4278         found = 0;
4279         for (i = 0; i < tdef->rows; ++i) {
4280                 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
4281                 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
4282                         token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
4283                         klass = mono_class_get_full (image, token, context);
4284                         cons = g_list_append (cons, klass);
4285                         ++found;
4286                 } else {
4287                         /* contiguous list finished */
4288                         if (found)
4289                                 break;
4290                 }
4291         }
4292         if (!found)
4293                 return TRUE;
4294         res = g_new0 (MonoClass*, found + 1);
4295         for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
4296                 res [i] = tmp->data;
4297         }
4298         g_list_free (cons);
4299         *constraints = res;
4300         return TRUE;
4301 }
4302
4303 /*
4304  * mono_metadata_get_generic_param_row:
4305  *
4306  * @image:
4307  * @token: TypeOrMethodDef token, owner for GenericParam
4308  * @owner: coded token, set on return
4309  * 
4310  * Returns: 1-based row-id in the GenericParam table whose
4311  * owner is @token. 0 if not found.
4312  */
4313 guint32
4314 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
4315 {
4316         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
4317         guint32 cols [MONO_GENERICPARAM_SIZE];
4318         guint32 i;
4319
4320         g_assert (owner);
4321         if (!tdef->base)
4322                 return 0;
4323
4324         if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
4325                 *owner = MONO_TYPEORMETHOD_TYPE;
4326         else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
4327                 *owner = MONO_TYPEORMETHOD_METHOD;
4328         else {
4329                 g_error ("wrong token %x to get_generic_param_row", token);
4330                 return 0;
4331         }
4332         *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
4333
4334         for (i = 0; i < tdef->rows; ++i) {
4335                 mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
4336                 if (cols [MONO_GENERICPARAM_OWNER] == *owner)
4337                         return i + 1;
4338         }
4339
4340         return 0;
4341 }
4342
4343 gboolean
4344 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
4345 {
4346         guint32 owner;
4347         return mono_metadata_get_generic_param_row (image, token, &owner);
4348 }
4349
4350 /*
4351  * mono_metadata_load_generic_param_constraints:
4352  *
4353  * Load the generic parameter constraints for the newly created generic type or method
4354  * represented by @token and @container.  The @container is the new container which has
4355  * been returned by a call to mono_metadata_load_generic_params() with this @token.
4356  */
4357 void
4358 mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
4359                                               MonoGenericContainer *container)
4360 {
4361         guint32 start_row, i, owner;
4362         if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
4363                 return;
4364         for (i = 0; i < container->type_argc; i++)
4365                 get_constraints (image, start_row + i, &container->type_params [i].constraints, container);
4366 }
4367
4368 /*
4369  * mono_metadata_load_generic_params:
4370  *
4371  * Load the type parameters from the type or method definition @token.
4372  *
4373  * Use this method after parsing a type or method definition to figure out whether it's a generic
4374  * type / method.  When parsing a method definition, @parent_container points to the generic container
4375  * of the current class, if any.
4376  *
4377  * Note: This method does not load the constraints: for typedefs, this has to be done after fully
4378  *       creating the type.
4379  *
4380  * Returns: NULL if @token is not a generic type or method definition or the new generic container.
4381  *
4382  */
4383 MonoGenericContainer *
4384 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
4385 {
4386         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
4387         guint32 cols [MONO_GENERICPARAM_SIZE];
4388         guint32 i, owner = 0, n;
4389         MonoGenericContainer *container;
4390         MonoGenericParam *params;
4391
4392         if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
4393                 return NULL;
4394         mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
4395         params = NULL;
4396         n = 0;
4397         container = g_new0 (MonoGenericContainer, 1);
4398         do {
4399                 n++;
4400                 params = g_realloc (params, sizeof (MonoGenericParam) * n);
4401                 params [n - 1].owner = container;
4402                 params [n - 1].pklass = NULL;
4403                 params [n - 1].method = NULL;
4404                 params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS];
4405                 params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER];
4406                 params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
4407                 params [n - 1].constraints = NULL;
4408                 if (++i > tdef->rows)
4409                         break;
4410                 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
4411         } while (cols [MONO_GENERICPARAM_OWNER] == owner);
4412
4413         container->type_argc = n;
4414         container->type_params = params;
4415         container->parent = parent_container;
4416
4417         if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
4418                 container->is_method = 1;
4419
4420         container->context.container = container;
4421
4422         return container;
4423 }
4424
4425 gboolean
4426 mono_type_is_byref (MonoType *type)
4427 {
4428         return type->byref;
4429 }
4430
4431 int
4432 mono_type_get_type (MonoType *type)
4433 {
4434         return type->type;
4435 }
4436
4437 /* For MONO_TYPE_FNPTR */
4438 MonoMethodSignature*
4439 mono_type_get_signature (MonoType *type)
4440 {
4441         return type->data.method;
4442 }
4443
4444 /* For MONO_TYPE_CLASS, VALUETYPE */
4445 MonoClass*
4446 mono_type_get_class (MonoType *type)
4447 {
4448         return type->data.klass;
4449 }
4450
4451 /* For MONO_TYPE_ARRAY */
4452 MonoArrayType*
4453 mono_type_get_array_type (MonoType *type)
4454 {
4455         return type->data.array;
4456 }
4457
4458 MonoClass*
4459 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
4460 {
4461         /* FIXME: implement */
4462         return NULL;
4463 }
4464
4465 MonoType*
4466 mono_signature_get_return_type (MonoMethodSignature *sig)
4467 {
4468         return sig->ret;
4469 }
4470
4471 MonoType*
4472 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
4473 {
4474         MonoType** type;
4475         if (!iter)
4476                 return NULL;
4477         if (!*iter) {
4478                 /* start from the first */
4479                 if (sig->param_count) {
4480                         *iter = &sig->params [0];
4481                         return sig->params [0];
4482                 } else {
4483                         /* no method */
4484                         return NULL;
4485                 }
4486         }
4487         type = *iter;
4488         type++;
4489         if (type < &sig->params [sig->param_count]) {
4490                 *iter = type;
4491                 return *type;
4492         }
4493         return NULL;
4494 }
4495
4496 guint32
4497 mono_signature_get_param_count (MonoMethodSignature *sig)
4498 {
4499         return sig->param_count;
4500 }
4501
4502 guint32
4503 mono_signature_get_call_conv (MonoMethodSignature *sig)
4504 {
4505         return sig->call_convention;
4506 }
4507
4508 int
4509 mono_signature_vararg_start (MonoMethodSignature *sig)
4510 {
4511         return sig->sentinelpos;
4512 }
4513
4514 gboolean
4515 mono_signature_is_instance (MonoMethodSignature *sig)
4516 {
4517         return sig->hasthis;
4518 }
4519
4520 gboolean
4521 mono_signature_explicit_this (MonoMethodSignature *sig)
4522 {
4523         return sig->explicit_this;
4524 }
4525
4526 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
4527 guint
4528 mono_aligned_addr_hash (gconstpointer ptr)
4529 {
4530         return GPOINTER_TO_UINT (ptr) >> 3;
4531 }
4532