Implement better explicit override checks.
[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  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  */
11
12 #include <config.h>
13 #ifdef HAVE_ALLOCA_H
14 #include <alloca.h>
15 #endif
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <glib.h>
20 #include "metadata.h"
21 #include "tabledefs.h"
22 #include "mono-endian.h"
23 #include "cil-coff.h"
24 #include "tokentype.h"
25 #include "metadata-internals.h"
26 #include "class-internals.h"
27 #include "verify-internals.h"
28 #include "class.h"
29 #include "marshal.h"
30 #include "gc-internal.h"
31 #include <mono/utils/mono-error-internals.h>
32  
33 /* Auxiliary structure used for caching inflated signatures */
34 typedef struct {
35         MonoMethodSignature *sig;
36         MonoGenericContext context;
37 } MonoInflatedMethodSignature;
38
39 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
40                                          const char *ptr, const char **rptr);
41
42 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
43 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
44 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
45 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
46                                                     gboolean signature_only);
47 static GSList* free_generic_inst_dependents (MonoGenericInst *ginst);
48 static void free_generic_inst (MonoGenericInst *ginst);
49 static GSList* free_generic_class_dependents (MonoGenericClass *ginst);
50 static void free_generic_class (MonoGenericClass *ginst);
51 static void free_inflated_method (MonoMethodInflated *method);
52 static void free_inflated_signature (MonoInflatedMethodSignature *sig);
53 static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
54
55 /*
56  * This enumeration is used to describe the data types in the metadata
57  * tables
58  */
59 enum {
60         MONO_MT_END,
61
62         /* Sized elements */
63         MONO_MT_UINT32,
64         MONO_MT_UINT16,
65         MONO_MT_UINT8,
66
67         /* Index into Blob heap */
68         MONO_MT_BLOB_IDX,
69
70         /* Index into String heap */
71         MONO_MT_STRING_IDX,
72
73         /* GUID index */
74         MONO_MT_GUID_IDX,
75
76         /* Pointer into a table */
77         MONO_MT_TABLE_IDX,
78
79         /* HasConstant:Parent pointer (Param, Field or Property) */
80         MONO_MT_CONST_IDX,
81
82         /* HasCustomAttribute index.  Indexes any table except CustomAttribute */
83         MONO_MT_HASCAT_IDX,
84         
85         /* CustomAttributeType encoded index */
86         MONO_MT_CAT_IDX,
87
88         /* HasDeclSecurity index: TypeDef Method or Assembly */
89         MONO_MT_HASDEC_IDX,
90
91         /* Implementation coded index: File, Export AssemblyRef */
92         MONO_MT_IMPL_IDX,
93
94         /* HasFieldMarshal coded index: Field or Param table */
95         MONO_MT_HFM_IDX,
96
97         /* MemberForwardedIndex: Field or Method */
98         MONO_MT_MF_IDX,
99
100         /* TypeDefOrRef coded index: typedef, typeref, typespec */
101         MONO_MT_TDOR_IDX,
102
103         /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
104         MONO_MT_MRP_IDX,
105
106         /* MethodDefOrRef coded index: Method or Member Ref table */
107         MONO_MT_MDOR_IDX,
108
109         /* HasSemantic coded index: Event or Property */
110         MONO_MT_HS_IDX,
111
112         /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
113         MONO_MT_RS_IDX
114 };
115
116 const static unsigned char TableSchemas [] = {
117 #define ASSEMBLY_SCHEMA_OFFSET 0
118         MONO_MT_UINT32,     /* "HashId" }, */
119         MONO_MT_UINT16,     /* "Major" },  */
120         MONO_MT_UINT16,     /* "Minor" }, */
121         MONO_MT_UINT16,     /* "BuildNumber" }, */
122         MONO_MT_UINT16,     /* "RevisionNumber" }, */
123         MONO_MT_UINT32,     /* "Flags" }, */
124         MONO_MT_BLOB_IDX,   /* "PublicKey" }, */
125         MONO_MT_STRING_IDX, /* "Name" }, */
126         MONO_MT_STRING_IDX, /* "Culture" }, */
127         MONO_MT_END,
128
129 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
130         MONO_MT_UINT32,     /* "OSPlatformID" }, */
131         MONO_MT_UINT32,     /* "OSMajor" }, */
132         MONO_MT_UINT32,     /* "OSMinor" }, */
133         MONO_MT_END,
134
135 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
136         MONO_MT_UINT32,     /* "Processor" }, */
137         MONO_MT_END,
138
139 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
140         MONO_MT_UINT16,     /* "Major" }, */
141         MONO_MT_UINT16,     /* "Minor" }, */
142         MONO_MT_UINT16,     /* "Build" }, */
143         MONO_MT_UINT16,     /* "Revision" }, */
144         MONO_MT_UINT32,     /* "Flags" }, */
145         MONO_MT_BLOB_IDX,   /* "PublicKeyOrToken" }, */
146         MONO_MT_STRING_IDX, /* "Name" }, */
147         MONO_MT_STRING_IDX, /* "Culture" }, */
148         MONO_MT_BLOB_IDX,   /* "HashValue" }, */
149         MONO_MT_END,
150
151 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
152         MONO_MT_UINT32,     /* "OSPlatformID" }, */
153         MONO_MT_UINT32,     /* "OSMajorVersion" }, */
154         MONO_MT_UINT32,     /* "OSMinorVersion" }, */
155         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
156         MONO_MT_END,
157
158 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
159         MONO_MT_UINT32,     /* "Processor" }, */
160         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
161         MONO_MT_END,
162
163 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
164         MONO_MT_UINT16,     /* "PackingSize" }, */
165         MONO_MT_UINT32,     /* "ClassSize" }, */
166         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
167         MONO_MT_END,
168
169 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
170         MONO_MT_UINT8,      /* "Type" }, */
171         MONO_MT_UINT8,      /* "PaddingZero" }, */
172         MONO_MT_CONST_IDX,  /* "Parent" }, */
173         MONO_MT_BLOB_IDX,   /* "Value" }, */
174         MONO_MT_END,
175
176 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
177         MONO_MT_HASCAT_IDX, /* "Parent" }, */
178         MONO_MT_CAT_IDX,    /* "Type" }, */
179         MONO_MT_BLOB_IDX,   /* "Value" }, */
180         MONO_MT_END,
181
182 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
183         MONO_MT_UINT16,     /* "Action" }, */
184         MONO_MT_HASDEC_IDX, /* "Parent" }, */
185         MONO_MT_BLOB_IDX,   /* "PermissionSet" }, */
186         MONO_MT_END,
187
188 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
189         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
190         MONO_MT_TABLE_IDX,  /* "EventList:Event" }, */
191         MONO_MT_END,
192
193 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
194         MONO_MT_UINT16,     /* "EventFlags#EventAttribute" }, */
195         MONO_MT_STRING_IDX, /* "Name" }, */
196         MONO_MT_TDOR_IDX,  /* "EventType" }, TypeDef or TypeRef or TypeSpec  */
197         MONO_MT_END,
198
199 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
200         MONO_MT_TABLE_IDX,  /* "Event" }, */
201         MONO_MT_END,
202
203 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
204         MONO_MT_UINT32,     /* "Flags" }, */
205         MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
206         MONO_MT_STRING_IDX, /* "TypeName" }, */
207         MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
208         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
209         MONO_MT_END,
210
211 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
212         MONO_MT_UINT16,     /* "Flags" }, */
213         MONO_MT_STRING_IDX, /* "Name" }, */
214         MONO_MT_BLOB_IDX,   /* "Signature" }, */
215         MONO_MT_END,
216
217 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
218         MONO_MT_UINT32,     /* "Offset" }, */
219         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
220         MONO_MT_END,
221
222 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
223         MONO_MT_HFM_IDX,    /* "Parent" }, */
224         MONO_MT_BLOB_IDX,   /* "NativeType" }, */
225         MONO_MT_END,
226
227 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
228         MONO_MT_UINT32,     /* "RVA" }, */
229         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
230         MONO_MT_END,
231
232 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
233         MONO_MT_TABLE_IDX,  /* "Field" }, */
234         MONO_MT_END,
235
236 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
237         MONO_MT_UINT32,     /* "Flags" }, */
238         MONO_MT_STRING_IDX, /* "Name" }, */
239         MONO_MT_BLOB_IDX,   /* "Value" },  */
240         MONO_MT_END,
241
242 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
243         MONO_MT_UINT16,     /* "MappingFlag" }, */
244         MONO_MT_MF_IDX,     /* "MemberForwarded" }, */
245         MONO_MT_STRING_IDX, /* "ImportName" }, */
246         MONO_MT_TABLE_IDX,  /* "ImportScope:ModuleRef" }, */
247         MONO_MT_END,
248
249 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
250         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" },  */
251         MONO_MT_TDOR_IDX,  /* "Interface=TypeDefOrRef" }, */
252         MONO_MT_END,
253
254 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
255         MONO_MT_UINT32,     /* "Offset" }, */
256         MONO_MT_UINT32,     /* "Flags" }, */
257         MONO_MT_STRING_IDX, /* "Name" }, */
258         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
259         MONO_MT_END,
260
261 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
262         MONO_MT_MRP_IDX,    /* "Class" }, */
263         MONO_MT_STRING_IDX, /* "Name" }, */
264         MONO_MT_BLOB_IDX,   /* "Signature" }, */
265         MONO_MT_END,
266
267 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
268         MONO_MT_UINT32,     /* "RVA" }, */
269         MONO_MT_UINT16,     /* "ImplFlags#MethodImplAttributes" }, */
270         MONO_MT_UINT16,     /* "Flags#MethodAttribute" }, */
271         MONO_MT_STRING_IDX, /* "Name" }, */
272         MONO_MT_BLOB_IDX,   /* "Signature" }, */
273         MONO_MT_TABLE_IDX,  /* "ParamList:Param" }, */
274         MONO_MT_END,
275
276 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
277         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" }, */
278         MONO_MT_MDOR_IDX,   /* "MethodBody" }, */
279         MONO_MT_MDOR_IDX,   /* "MethodDeclaration" }, */
280         MONO_MT_END,
281
282 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
283         MONO_MT_UINT16,     /* "MethodSemantic" }, */
284         MONO_MT_TABLE_IDX,  /* "Method:Method" }, */
285         MONO_MT_HS_IDX,     /* "Association" }, */
286         MONO_MT_END,
287
288 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
289         MONO_MT_TABLE_IDX,  /* "Method" }, */
290         MONO_MT_END,
291
292 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
293         MONO_MT_UINT16,     /* "Generation" }, */
294         MONO_MT_STRING_IDX, /* "Name" }, */
295         MONO_MT_GUID_IDX,   /* "MVID" }, */
296         MONO_MT_GUID_IDX,   /* "EncID" }, */
297         MONO_MT_GUID_IDX,   /* "EncBaseID" }, */
298         MONO_MT_END,
299
300 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
301         MONO_MT_STRING_IDX, /* "Name" }, */
302         MONO_MT_END,
303
304 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
305         MONO_MT_TABLE_IDX,  /* "NestedClass:TypeDef" }, */
306         MONO_MT_TABLE_IDX,  /* "EnclosingClass:TypeDef" }, */
307         MONO_MT_END,
308
309 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
310         MONO_MT_UINT16,     /* "Flags" }, */
311         MONO_MT_UINT16,     /* "Sequence" }, */
312         MONO_MT_STRING_IDX, /* "Name" }, */
313         MONO_MT_END,
314
315 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
316         MONO_MT_TABLE_IDX,  /* "Param" }, */
317         MONO_MT_END,
318
319 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
320         MONO_MT_UINT16,     /* "Flags" }, */
321         MONO_MT_STRING_IDX, /* "Name" }, */
322         MONO_MT_BLOB_IDX,   /* "Type" }, */
323         MONO_MT_END,
324
325 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
326         MONO_MT_TABLE_IDX, /* "Property" }, */
327         MONO_MT_END,
328
329 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
330         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
331         MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
332         MONO_MT_END,
333
334 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
335         MONO_MT_BLOB_IDX,   /* "Signature" }, */
336         MONO_MT_END,
337
338 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
339         MONO_MT_UINT32,     /* "Flags" }, */
340         MONO_MT_STRING_IDX, /* "Name" }, */
341         MONO_MT_STRING_IDX, /* "Namespace" }, */
342         MONO_MT_TDOR_IDX,   /* "Extends" }, */
343         MONO_MT_TABLE_IDX,  /* "FieldList:Field" }, */
344         MONO_MT_TABLE_IDX,  /* "MethodList:Method" }, */
345         MONO_MT_END,
346
347 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
348         MONO_MT_RS_IDX,     /* "ResolutionScope=ResolutionScope" }, */
349         MONO_MT_STRING_IDX, /* "Name" }, */
350         MONO_MT_STRING_IDX, /* "Namespace" }, */
351         MONO_MT_END,
352
353 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
354         MONO_MT_BLOB_IDX,   /* "Signature" }, */
355         MONO_MT_END,
356
357 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
358         MONO_MT_UINT16,     /* "Number" }, */
359         MONO_MT_UINT16,     /* "Flags" }, */
360         MONO_MT_TABLE_IDX,  /* "Owner" },  TypeDef or MethodDef */
361         MONO_MT_STRING_IDX, /* "Name" }, */
362         MONO_MT_END,
363
364 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
365         MONO_MT_MDOR_IDX,   /* "Method" }, */
366         MONO_MT_BLOB_IDX,   /* "Signature" }, */
367         MONO_MT_END,
368
369 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
370         MONO_MT_TABLE_IDX,  /* "GenericParam" }, */
371         MONO_MT_TDOR_IDX,   /* "Constraint" }, */
372         MONO_MT_END,
373
374 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
375         MONO_MT_END
376 };
377
378 /* Must be the same order as MONO_TABLE_* */
379 const static unsigned char
380 table_description [] = {
381         MODULE_SCHEMA_OFFSET,
382         TYPEREF_SCHEMA_OFFSET,
383         TYPEDEF_SCHEMA_OFFSET,
384         FIELD_POINTER_SCHEMA_OFFSET,
385         FIELD_SCHEMA_OFFSET,
386         METHOD_POINTER_SCHEMA_OFFSET,
387         METHOD_SCHEMA_OFFSET,
388         PARAM_POINTER_SCHEMA_OFFSET,
389         PARAM_SCHEMA_OFFSET,
390         IFACEMAP_SCHEMA_OFFSET,
391         MEMBERREF_SCHEMA_OFFSET, /* 0xa */
392         CONSTANT_SCHEMA_OFFSET,
393         CUSTOM_ATTR_SCHEMA_OFFSET,
394         FIELD_MARSHAL_SCHEMA_OFFSET,
395         DECL_SEC_SCHEMA_OFFSET,
396         CLASS_LAYOUT_SCHEMA_OFFSET,
397         FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
398         STDALON_SIG_SCHEMA_OFFSET,
399         EVENTMAP_SCHEMA_OFFSET,
400         EVENT_POINTER_SCHEMA_OFFSET,
401         EVENT_SCHEMA_OFFSET,
402         PROPERTY_MAP_SCHEMA_OFFSET,
403         PROPERTY_POINTER_SCHEMA_OFFSET,
404         PROPERTY_SCHEMA_OFFSET,
405         METHOD_SEMA_SCHEMA_OFFSET,
406         METHOD_IMPL_SCHEMA_OFFSET,
407         MODULEREF_SCHEMA_OFFSET, /* 0x1a */
408         TYPESPEC_SCHEMA_OFFSET,
409         IMPLMAP_SCHEMA_OFFSET,
410         FIELD_RVA_SCHEMA_OFFSET,
411         NULL_SCHEMA_OFFSET,
412         NULL_SCHEMA_OFFSET,
413         ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
414         ASSEMBLYPROC_SCHEMA_OFFSET,
415         ASSEMBLYOS_SCHEMA_OFFSET,
416         ASSEMBLYREF_SCHEMA_OFFSET,
417         ASSEMBLYREFPROC_SCHEMA_OFFSET,
418         ASSEMBLYREFOS_SCHEMA_OFFSET,
419         FILE_SCHEMA_OFFSET,
420         EXPORTED_TYPE_SCHEMA_OFFSET,
421         MANIFEST_SCHEMA_OFFSET,
422         NESTED_CLASS_SCHEMA_OFFSET,
423         GENPARAM_SCHEMA_OFFSET, /* 0x2a */
424         METHOD_SPEC_SCHEMA_OFFSET,
425         GEN_CONSTRAINT_SCHEMA_OFFSET
426 };
427
428 #ifdef HAVE_ARRAY_ELEM_INIT
429 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
430 #define MSGSTRFIELD1(line) str##line
431 static const struct msgstr_t {
432 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
433 #include "mono/cil/tables.def"
434 #undef TABLEDEF
435 } tablestr = {
436 #define TABLEDEF(a,b) b,
437 #include "mono/cil/tables.def"
438 #undef TABLEDEF
439 };
440 static const gint16 tableidx [] = {
441 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
442 #include "mono/cil/tables.def"
443 #undef TABLEDEF
444 };
445
446 #else
447 #define TABLEDEF(a,b) b,
448 static const char* const
449 mono_tables_names [] = {
450 #include "mono/cil/tables.def"
451         NULL
452 };
453
454 #endif
455
456 /**
457  * mono_meta_table_name:
458  * @table: table index
459  *
460  * Returns the name of the given ECMA metadata logical format table
461  * as described in ECMA 335, Partition II, Section 22.
462  * 
463  * Returns: the name for the @table index
464  */
465 const char *
466 mono_meta_table_name (int table)
467 {
468         if ((table < 0) || (table > MONO_TABLE_LAST))
469                 return "";
470
471 #ifdef HAVE_ARRAY_ELEM_INIT
472         return (const char*)&tablestr + tableidx [table];
473 #else
474         return mono_tables_names [table];
475 #endif
476 }
477
478 /* The guy who wrote the spec for this should not be allowed near a
479  * computer again.
480  
481 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
482 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
483 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
484 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
485 inverse of this mapping.
486
487  */
488 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
489 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
490
491 /* Reference: Partition II - 23.2.6 */
492 /*
493  * mono_metadata_compute_size:
494  * @meta: metadata context
495  * @tableindex: metadata table number
496  * @result_bitfield: pointer to guint32 where to store additional info
497  * 
498  * mono_metadata_compute_size() computes the lenght in bytes of a single
499  * row in a metadata table. The size of each column is encoded in the
500  * @result_bitfield return value along with the number of columns in the table.
501  * the resulting bitfield should be handed to the mono_metadata_table_size()
502  * and mono_metadata_table_count() macros.
503  * This is a Mono runtime internal only function.
504  */
505 int
506 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
507 {
508         guint32 bitfield = 0;
509         int size = 0, field_size = 0;
510         int i, n, code;
511         int shift = 0;
512         const unsigned char *description = TableSchemas + table_description [tableindex];
513
514         for (i = 0; (code = description [i]) != MONO_MT_END; i++){
515                 switch (code){
516                 case MONO_MT_UINT32:
517                         field_size = 4; break;
518                         
519                 case MONO_MT_UINT16:
520                         field_size = 2; break;
521                         
522                 case MONO_MT_UINT8:
523                         field_size = 1; break;
524                         
525                 case MONO_MT_BLOB_IDX:
526                         field_size = meta->idx_blob_wide ? 4 : 2; break;
527                         
528                 case MONO_MT_STRING_IDX:
529                         field_size = meta->idx_string_wide ? 4 : 2; break;
530                         
531                 case MONO_MT_GUID_IDX:
532                         field_size = meta->idx_guid_wide ? 4 : 2; break;
533
534                 case MONO_MT_TABLE_IDX:
535                         /* Uhm, a table index can point to other tables besides the current one
536                          * so, it's not correct to use the rowcount of the current table to
537                          * get the size for this column - lupus 
538                          */
539                         switch (tableindex) {
540                         case MONO_TABLE_ASSEMBLYREFOS:
541                                 g_assert (i == 3);
542                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
543                         case MONO_TABLE_ASSEMBLYREFPROCESSOR:
544                                 g_assert (i == 1);
545                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
546                         case MONO_TABLE_CLASSLAYOUT:
547                                 g_assert (i == 2);
548                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
549                         case MONO_TABLE_EVENTMAP:
550                                 g_assert (i == 0 || i == 1);
551                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
552                                         idx_size(MONO_TABLE_TYPEDEF); 
553                                 break;
554                         case MONO_TABLE_EVENT_POINTER:
555                                 g_assert (i == 0);
556                                 field_size = idx_size (MONO_TABLE_EVENT); break;
557                         case MONO_TABLE_EXPORTEDTYPE:
558                                 g_assert (i == 1);
559                                 /* the index is in another metadata file, so it must be 4 */
560                                 field_size = 4; break;
561                         case MONO_TABLE_FIELDLAYOUT:
562                                 g_assert (i == 1);
563                                 field_size = idx_size (MONO_TABLE_FIELD); break;
564                         case MONO_TABLE_FIELDRVA:
565                                 g_assert (i == 1);
566                                 field_size = idx_size (MONO_TABLE_FIELD); break;
567                         case MONO_TABLE_FIELD_POINTER:
568                                 g_assert (i == 0);
569                                 field_size = idx_size (MONO_TABLE_FIELD); break;
570                         case MONO_TABLE_IMPLMAP:
571                                 g_assert (i == 3);
572                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
573                         case MONO_TABLE_INTERFACEIMPL:
574                                 g_assert (i == 0);
575                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
576                         case MONO_TABLE_METHOD:
577                                 g_assert (i == 5);
578                                 field_size = idx_size (MONO_TABLE_PARAM); break;
579                         case MONO_TABLE_METHODIMPL:
580                                 g_assert (i == 0);
581                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
582                         case MONO_TABLE_METHODSEMANTICS:
583                                 g_assert (i == 1);
584                                 field_size = idx_size (MONO_TABLE_METHOD); break;
585                         case MONO_TABLE_METHOD_POINTER:
586                                 g_assert (i == 0);
587                                 field_size = idx_size (MONO_TABLE_METHOD); break;
588                         case MONO_TABLE_NESTEDCLASS:
589                                 g_assert (i == 0 || i == 1);
590                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
591                         case MONO_TABLE_PARAM_POINTER:
592                                 g_assert (i == 0);
593                                 field_size = idx_size (MONO_TABLE_PARAM); break;
594                         case MONO_TABLE_PROPERTYMAP:
595                                 g_assert (i == 0 || i == 1);
596                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
597                                         idx_size(MONO_TABLE_TYPEDEF); 
598                                 break;
599                         case MONO_TABLE_PROPERTY_POINTER:
600                                 g_assert (i == 0);
601                                 field_size = idx_size (MONO_TABLE_PROPERTY); break;
602                         case MONO_TABLE_TYPEDEF:
603                                 g_assert (i == 4 || i == 5);
604                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
605                                         idx_size(MONO_TABLE_METHOD);
606                                 break;
607                         case MONO_TABLE_GENERICPARAM:
608                                 g_assert (i == 2);
609                                 n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
610                                 /*This is a coded token for 2 tables, so takes 1 bit */
611                                 field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
612                                 break;
613                         case MONO_TABLE_GENERICPARAMCONSTRAINT:
614                                 g_assert (i == 0);
615                                 field_size = idx_size (MONO_TABLE_GENERICPARAM);
616                                 break;
617                                 
618                         default:
619                                 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
620                         }
621                         break;
622
623                         /*
624                          * HasConstant: ParamDef, FieldDef, Property
625                          */
626                 case MONO_MT_CONST_IDX:
627                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
628                                  meta->tables [MONO_TABLE_FIELD].rows);
629                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
630
631                         /* 2 bits to encode tag */
632                         field_size = rtsize (n, 16-2);
633                         break;
634
635                         /*
636                          * HasCustomAttribute: points to any table but
637                          * itself.
638                          */
639                 case MONO_MT_HASCAT_IDX:
640                         /*
641                          * We believe that since the signature and
642                          * permission are indexing the Blob heap,
643                          * we should consider the blob size first
644                          */
645                         /* I'm not a believer - lupus
646                         if (meta->idx_blob_wide){
647                                 field_size = 4;
648                                 break;
649                         }*/
650                         
651                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
652                                  meta->tables [MONO_TABLE_FIELD].rows);
653                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
654                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
655                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
656                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
657                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
658                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
659                         n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
660                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
661                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
662                         n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
663                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
664                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
665                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
666                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
667                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
668                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
669                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
670
671                         /* 5 bits to encode */
672                         field_size = rtsize (n, 16-5);
673                         break;
674
675                         /*
676                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
677                          * MemberRef and String.  
678                          */
679                 case MONO_MT_CAT_IDX:
680                         /* String is a heap, if it is wide, we know the size */
681                         /* See above, nope. 
682                         if (meta->idx_string_wide){
683                                 field_size = 4;
684                                 break;
685                         }*/
686                         
687                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
688                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
689                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
690                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
691
692                         /* 3 bits to encode */
693                         field_size = rtsize (n, 16-3);
694                         break;
695
696                         /*
697                          * HasDeclSecurity: Typedef, MethodDef, Assembly
698                          */
699                 case MONO_MT_HASDEC_IDX:
700                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
701                                  meta->tables [MONO_TABLE_METHOD].rows);
702                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
703
704                         /* 2 bits to encode */
705                         field_size = rtsize (n, 16-2);
706                         break;
707
708                         /*
709                          * Implementation: File, AssemblyRef, ExportedType
710                          */
711                 case MONO_MT_IMPL_IDX:
712                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
713                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
714                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
715
716                         /* 2 bits to encode tag */
717                         field_size = rtsize (n, 16-2);
718                         break;
719
720                         /*
721                          * HasFieldMarshall: FieldDef, ParamDef
722                          */
723                 case MONO_MT_HFM_IDX:
724                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
725                                  meta->tables [MONO_TABLE_PARAM].rows);
726
727                         /* 1 bit used to encode tag */
728                         field_size = rtsize (n, 16-1);
729                         break;
730
731                         /*
732                          * MemberForwarded: FieldDef, MethodDef
733                          */
734                 case MONO_MT_MF_IDX:
735                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
736                                  meta->tables [MONO_TABLE_METHOD].rows);
737
738                         /* 1 bit used to encode tag */
739                         field_size = rtsize (n, 16-1);
740                         break;
741
742                         /*
743                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
744                          * LAMESPEC
745                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
746                          */
747                 case MONO_MT_TDOR_IDX:
748                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
749                                  meta->tables [MONO_TABLE_TYPEREF].rows);
750                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
751
752                         /* 2 bits to encode */
753                         field_size = rtsize (n, 16-2);
754                         break;
755
756                         /*
757                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
758                          */
759                 case MONO_MT_MRP_IDX:
760                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
761                                  meta->tables [MONO_TABLE_TYPEREF].rows);
762                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
763                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
764                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
765                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
766
767                         /* 3 bits to encode */
768                         field_size = rtsize (n, 16 - 3);
769                         break;
770                         
771                         /*
772                          * MethodDefOrRef: MethodDef, MemberRef
773                          */
774                 case MONO_MT_MDOR_IDX:
775                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
776                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
777
778                         /* 1 bit used to encode tag */
779                         field_size = rtsize (n, 16-1);
780                         break;
781                         
782                         /*
783                          * HasSemantics: Property, Event
784                          */
785                 case MONO_MT_HS_IDX:
786                         n = MAX (meta->tables [MONO_TABLE_PROPERTY].rows,
787                                  meta->tables [MONO_TABLE_EVENT].rows);
788
789                         /* 1 bit used to encode tag */
790                         field_size = rtsize (n, 16-1);
791                         break;
792
793                         /*
794                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
795                          */
796                 case MONO_MT_RS_IDX:
797                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
798                                  meta->tables [MONO_TABLE_MODULEREF].rows);
799                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
800                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
801
802                         /* 2 bits used to encode tag (ECMA spec claims 3) */
803                         field_size = rtsize (n, 16 - 2);
804                         break;
805                 }
806
807                 /*
808                  * encode field size as follows (we just need to
809                  * distinguish them).
810                  *
811                  * 4 -> 3
812                  * 2 -> 1
813                  * 1 -> 0
814                  */
815                 bitfield |= (field_size-1) << shift;
816                 shift += 2;
817                 size += field_size;
818                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
819         }
820
821         *result_bitfield = (i << 24) | bitfield;
822         return size;
823 }
824
825 /**
826  * mono_metadata_compute_table_bases:
827  * @meta: metadata context to compute table values
828  *
829  * Computes the table bases for the metadata structure.
830  * This is an internal function used by the image loader code.
831  */
832 void
833 mono_metadata_compute_table_bases (MonoImage *meta)
834 {
835         int i;
836         const char *base = meta->tables_base;
837         
838         for (i = 0; i < MONO_TABLE_NUM; i++) {
839                 MonoTableInfo *table = &meta->tables [i];
840                 if (table->rows == 0)
841                         continue;
842
843                 table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
844                 table->base = base;
845                 base += table->rows * table->row_size;
846         }
847 }
848
849 /**
850  * mono_metadata_locate:
851  * @meta: metadata context
852  * @table: table code.
853  * @idx: index of element to retrieve from @table.
854  *
855  * Returns: a pointer to the @idx element in the metadata table
856  * whose code is @table.
857  */
858 const char *
859 mono_metadata_locate (MonoImage *meta, int table, int idx)
860 {
861         /* idx == 0 refers always to NULL */
862         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
863            
864         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
865 }
866
867 /**
868  * mono_metadata_locate_token:
869  * @meta: metadata context
870  * @token: metadata token
871  *
872  * Returns: a pointer to the data in the metadata represented by the
873  * token #token.
874  */
875 const char *
876 mono_metadata_locate_token (MonoImage *meta, guint32 token)
877 {
878         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
879 }
880
881 /**
882  * mono_metadata_string_heap:
883  * @meta: metadata context
884  * @index: index into the string heap.
885  *
886  * Returns: an in-memory pointer to the @index in the string heap.
887  */
888 const char *
889 mono_metadata_string_heap (MonoImage *meta, guint32 index)
890 {
891         g_return_val_if_fail (index < meta->heap_strings.size, "");
892         return meta->heap_strings.data + index;
893 }
894
895 /**
896  * mono_metadata_user_string:
897  * @meta: metadata context
898  * @index: index into the user string heap.
899  *
900  * Returns: an in-memory pointer to the @index in the user string heap ("#US").
901  */
902 const char *
903 mono_metadata_user_string (MonoImage *meta, guint32 index)
904 {
905         g_return_val_if_fail (index < meta->heap_us.size, "");
906         return meta->heap_us.data + index;
907 }
908
909 /**
910  * mono_metadata_blob_heap:
911  * @meta: metadata context
912  * @index: index into the blob.
913  *
914  * Returns: an in-memory pointer to the @index in the Blob heap.
915  */
916 const char *
917 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
918 {
919         g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
920         return meta->heap_blob.data + index;
921 }
922
923 /**
924  * mono_metadata_guid_heap:
925  * @meta: metadata context
926  * @index: index into the guid heap.
927  *
928  * Returns: an in-memory pointer to the @index in the guid heap.
929  */
930 const char *
931 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
932 {
933         --index;
934         index *= 16; /* adjust for guid size and 1-based index */
935         g_return_val_if_fail (index < meta->heap_guid.size, "");
936         return meta->heap_guid.data + index;
937 }
938
939 static const unsigned char *
940 dword_align (const unsigned char *ptr)
941 {
942 #if SIZEOF_VOID_P == 8
943         return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
944 #else
945         return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
946 #endif
947 }
948
949 /**
950  * mono_metadata_decode_row:
951  * @t: table to extract information from.
952  * @idx: index in table.
953  * @res: array of @res_size cols to store the results in
954  *
955  * This decompresses the metadata element @idx in table @t
956  * into the guint32 @res array that has res_size elements
957  */
958 void
959 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
960 {
961         guint32 bitfield = t->size_bitfield;
962         int i, count = mono_metadata_table_count (bitfield);
963         const char *data;
964
965         g_assert (idx < t->rows);
966         data = t->base + idx * t->row_size;
967         
968         g_assert (res_size == count);
969
970         for (i = 0; i < count; i++) {
971                 int n = mono_metadata_table_size (bitfield, i);
972
973                 switch (n){
974                 case 1:
975                         res [i] = *data; break;
976                 case 2:
977                         res [i] = read16 (data); break;
978                 case 4:
979                         res [i] = read32 (data); break;
980                 default:
981                         g_assert_not_reached ();
982                 }
983                 data += n;
984         }
985 }
986
987 /**
988  * mono_metadata_decode_row_col:
989  * @t: table to extract information from.
990  * @idx: index for row in table.
991  * @col: column in the row.
992  *
993  * This function returns the value of column @col from the @idx
994  * row in the table @t.
995  */
996 guint32
997 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
998 {
999         guint32 bitfield = t->size_bitfield;
1000         int i;
1001         register const char *data; 
1002         register int n;
1003         
1004         g_assert (idx < t->rows);
1005         g_assert (col < mono_metadata_table_count (bitfield));
1006         data = t->base + idx * t->row_size;
1007
1008         n = mono_metadata_table_size (bitfield, 0);
1009         for (i = 0; i < col; ++i) {
1010                 data += n;
1011                 n = mono_metadata_table_size (bitfield, i + 1);
1012         }
1013         switch (n) {
1014         case 1:
1015                 return *data;
1016         case 2:
1017                 return read16 (data);
1018         case 4:
1019                 return read32 (data);
1020         default:
1021                 g_assert_not_reached ();
1022         }
1023         return 0;
1024 }
1025
1026 /**
1027  * mono_metadata_decode_blob_size:
1028  * @ptr: pointer to a blob object
1029  * @rptr: the new position of the pointer
1030  *
1031  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1032  *
1033  * Returns: the size of the blob object
1034  */
1035 guint32
1036 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
1037 {
1038         const unsigned char *ptr = (const unsigned char *)xptr;
1039         guint32 size;
1040         
1041         if ((*ptr & 0x80) == 0){
1042                 size = ptr [0] & 0x7f;
1043                 ptr++;
1044         } else if ((*ptr & 0x40) == 0){
1045                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
1046                 ptr += 2;
1047         } else {
1048                 size = ((ptr [0] & 0x1f) << 24) +
1049                         (ptr [1] << 16) +
1050                         (ptr [2] << 8) +
1051                         ptr [3];
1052                 ptr += 4;
1053         }
1054         if (rptr)
1055                 *rptr = (char*)ptr;
1056         return size;
1057 }
1058
1059 /**
1060  * mono_metadata_decode_value:
1061  * @ptr: pointer to decode from
1062  * @rptr: the new position of the pointer
1063  *
1064  * This routine decompresses 32-bit values as specified in the "Blob and
1065  * Signature" section (22.2)
1066  *
1067  * Returns: the decoded value
1068  */
1069 guint32
1070 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1071 {
1072         const unsigned char *ptr = (const unsigned char *) _ptr;
1073         unsigned char b = *ptr;
1074         guint32 len;
1075         
1076         if ((b & 0x80) == 0){
1077                 len = b;
1078                 ++ptr;
1079         } else if ((b & 0x40) == 0){
1080                 len = ((b & 0x3f) << 8 | ptr [1]);
1081                 ptr += 2;
1082         } else {
1083                 len = ((b & 0x1f) << 24) |
1084                         (ptr [1] << 16) |
1085                         (ptr [2] << 8) |
1086                         ptr [3];
1087                 ptr += 4;
1088         }
1089         if (rptr)
1090                 *rptr = (char*)ptr;
1091         
1092         return len;
1093 }
1094
1095 /**
1096  * mono_metadata_decode_signed_value:
1097  * @ptr: pointer to decode from
1098  * @rptr: the new position of the pointer
1099  *
1100  * This routine decompresses 32-bit signed values
1101  * (not specified in the spec)
1102  *
1103  * Returns: the decoded value
1104  */
1105 gint32
1106 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1107 {
1108         guint32 uval = mono_metadata_decode_value (ptr, rptr);
1109         gint32 ival = uval >> 1;
1110         if (!(uval & 1))
1111                 return ival;
1112         /* ival is a truncated 2's complement negative number.  */
1113         if (ival < 0x40)
1114                 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1115                 return ival - 0x40;
1116         if (ival < 0x2000)
1117                 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1118                 return ival - 0x2000;
1119         if (ival < 0x10000000)
1120                 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1121                 return ival - 0x10000000;
1122         g_assert (ival < 0x20000000);
1123         g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1124         return ival - 0x20000000;
1125 }
1126
1127 /* 
1128  * Translates the given 1-based index into the Method, Field, Event, or Param tables
1129  * using the *Ptr tables in uncompressed metadata, if they are available.
1130  *
1131  * FIXME: The caller is not forced to call this function, which is error-prone, since 
1132  * forgetting to call it would only show up as a bug on uncompressed metadata.
1133  */
1134 guint32
1135 mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
1136 {
1137         if (!image->uncompressed_metadata)
1138                 return idx;
1139
1140         switch (table) {
1141         case MONO_TABLE_METHOD:
1142                 if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
1143                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
1144                 else
1145                         return idx;
1146         case MONO_TABLE_FIELD:
1147                 if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
1148                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
1149                 else
1150                         return idx;
1151         case MONO_TABLE_EVENT:
1152                 if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
1153                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
1154                 else
1155                         return idx;
1156         case MONO_TABLE_PROPERTY:
1157                 if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
1158                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
1159                 else
1160                         return idx;
1161         case MONO_TABLE_PARAM:
1162                 if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
1163                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
1164                 else
1165                         return idx;
1166         default:
1167                 return idx;
1168         }
1169 }
1170
1171 /**
1172  * mono_metadata_decode_table_row:
1173  *
1174  *   Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1175  * uncompressed metadata into account, so it should be used to access the
1176  * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1177  * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1178  */
1179 void
1180 mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
1181 {
1182         if (image->uncompressed_metadata)
1183                 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1184
1185         mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
1186 }
1187
1188 /**
1189  * mono_metadata_decode_table_row_col:
1190  *
1191  *   Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1192  * uncompressed metadata into account, so it should be used to access the
1193  * Method, Field, Param and Event tables.
1194  */
1195 guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
1196 {
1197         if (image->uncompressed_metadata)
1198                 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1199
1200         return mono_metadata_decode_row_col (&image->tables [table], idx, col);
1201 }
1202
1203 /*
1204  * mono_metadata_parse_typedef_or_ref:
1205  * @m: a metadata context.
1206  * @ptr: a pointer to an encoded TypedefOrRef in @m
1207  * @rptr: pointer updated to match the end of the decoded stream
1208  *
1209  * Returns: a token valid in the @m metadata decoded from
1210  * the compressed representation.
1211  */
1212 guint32
1213 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1214 {
1215         guint32 token;
1216         token = mono_metadata_decode_value (ptr, &ptr);
1217         if (rptr)
1218                 *rptr = ptr;
1219         return mono_metadata_token_from_dor (token);
1220 }
1221
1222 /*
1223  * mono_metadata_parse_custom_mod:
1224  * @m: a metadata context.
1225  * @dest: storage where the info about the custom modifier is stored (may be NULL)
1226  * @ptr: a pointer to (possibly) the start of a custom modifier list
1227  * @rptr: pointer updated to match the end of the decoded stream
1228  *
1229  * Checks if @ptr points to a type custom modifier compressed representation.
1230  *
1231  * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1232  */
1233 int
1234 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1235 {
1236         MonoCustomMod local;
1237         if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1238                 if (!dest)
1239                         dest = &local;
1240                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1241                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1242                 return TRUE;
1243         }
1244         return FALSE;
1245 }
1246
1247 /*
1248  * mono_metadata_parse_array_internal:
1249  * @m: a metadata context.
1250  * @transient: whenever to allocate data from the heap
1251  * @ptr: a pointer to an encoded array description.
1252  * @rptr: pointer updated to match the end of the decoded stream
1253  *
1254  * Decodes the compressed array description found in the metadata @m at @ptr.
1255  *
1256  * Returns: a #MonoArrayType structure describing the array type
1257  * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1258  * on the value of @transient.
1259  *
1260  * LOCKING: Acquires the loader lock
1261  */
1262 static MonoArrayType *
1263 mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
1264                                                                         gboolean transient, const char *ptr, const char **rptr)
1265 {
1266         int i;
1267         MonoArrayType *array;
1268         MonoType *etype;
1269         
1270         array = transient ? g_malloc0 (sizeof (MonoArrayType)) : mono_image_alloc0 (m, sizeof (MonoArrayType));
1271         etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
1272         if (!etype)
1273                 return NULL;
1274         array->eklass = mono_class_from_mono_type (etype);
1275         array->rank = mono_metadata_decode_value (ptr, &ptr);
1276
1277         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1278         if (array->numsizes)
1279                 array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : mono_image_alloc0 (m, sizeof (int) * array->numsizes);
1280         for (i = 0; i < array->numsizes; ++i)
1281                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1282
1283         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1284         if (array->numlobounds)
1285                 array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
1286         for (i = 0; i < array->numlobounds; ++i)
1287                 array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1288
1289         if (rptr)
1290                 *rptr = ptr;
1291         return array;
1292 }
1293
1294 MonoArrayType *
1295 mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
1296                                                                 const char *ptr, const char **rptr)
1297 {
1298         return mono_metadata_parse_array_internal (m, container, FALSE, ptr, rptr);
1299 }
1300
1301 MonoArrayType *
1302 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1303 {
1304         return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
1305 }
1306
1307 /*
1308  * mono_metadata_free_array:
1309  * @array: array description
1310  *
1311  * Frees the array description returned from mono_metadata_parse_array().
1312  */
1313 void
1314 mono_metadata_free_array (MonoArrayType *array)
1315 {
1316         g_free (array->sizes);
1317         g_free (array->lobounds);
1318         g_free (array);
1319 }
1320
1321 /*
1322  * need to add common field and param attributes combinations:
1323  * [out] param
1324  * public static
1325  * public static literal
1326  * private
1327  * private static
1328  * private static literal
1329  */
1330 static const MonoType
1331 builtin_types[] = {
1332         /* data, attrs, type,              nmods, byref, pinned */
1333         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
1334         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
1335         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
1336         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
1337         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
1338         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
1339         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
1340         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
1341         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
1342         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
1343         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1344         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1345         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1346         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1347         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1348         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1349         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1350         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1351         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1352         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1353         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1354         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1355         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1356         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1357         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1358         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1359         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1360         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1361         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0},
1362         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1363         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1364         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1365         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1366         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1367 };
1368
1369 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1370
1371 static GHashTable *type_cache = NULL;
1372 static int next_generic_inst_id = 0;
1373
1374 static MonoImageSet *mscorlib_image_set;
1375 static GPtrArray *image_sets;
1376
1377 static guint mono_generic_class_hash (gconstpointer data);
1378
1379 /*
1380  * MonoTypes with modifies are never cached, so we never check or use that field.
1381  */
1382 static guint
1383 mono_type_hash (gconstpointer data)
1384 {
1385         const MonoType *type = (const MonoType *) data;
1386         if (type->type == MONO_TYPE_GENERICINST)
1387                 return mono_generic_class_hash (type->data.generic_class);
1388         else
1389                 return type->type | (type->byref << 8) | (type->attrs << 9);
1390 }
1391
1392 static gint
1393 mono_type_equal (gconstpointer ka, gconstpointer kb)
1394 {
1395         const MonoType *a = (const MonoType *) ka;
1396         const MonoType *b = (const MonoType *) kb;
1397         
1398         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1399                 return 0;
1400         /* need other checks */
1401         return 1;
1402 }
1403
1404 guint
1405 mono_metadata_generic_inst_hash (gconstpointer data)
1406 {
1407         const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1408         guint hash = 0;
1409         int i;
1410         
1411         for (i = 0; i < ginst->type_argc; ++i) {
1412                 hash *= 13;
1413                 hash += mono_metadata_type_hash (ginst->type_argv [i]);
1414         }
1415
1416         return hash ^ (ginst->is_open << 8);
1417 }
1418
1419 static gboolean
1420 mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
1421 {
1422         int i;
1423
1424 #ifndef MONO_SMALL_CONFIG
1425         if (a->id && b->id) {
1426                 if (a->id == b->id)
1427                         return TRUE;
1428                 if (!signature_only)
1429                         return FALSE;
1430         }
1431 #endif
1432
1433         if (a->is_open != b->is_open || a->type_argc != b->type_argc)
1434                 return FALSE;
1435         for (i = 0; i < a->type_argc; ++i) {
1436                 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
1437                         return FALSE;
1438         }
1439         return TRUE;
1440 }
1441
1442 gboolean
1443 mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1444 {
1445         const MonoGenericInst *a = (const MonoGenericInst *) ka;
1446         const MonoGenericInst *b = (const MonoGenericInst *) kb;
1447
1448         return mono_generic_inst_equal_full (a, b, FALSE);
1449 }
1450
1451 static guint
1452 mono_generic_class_hash (gconstpointer data)
1453 {
1454         const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1455         guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1456
1457         hash *= 13;
1458         hash += gclass->is_tb_open;
1459         hash += mono_metadata_generic_context_hash (&gclass->context);
1460
1461         return hash;
1462 }
1463
1464 static gboolean
1465 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1466 {
1467         const MonoGenericClass *a = (const MonoGenericClass *) ka;
1468         const MonoGenericClass *b = (const MonoGenericClass *) kb;
1469
1470         return _mono_metadata_generic_class_equal (a, b, FALSE);
1471 }
1472
1473 /**
1474  * mono_metadata_init:
1475  *
1476  * Initialize the global variables of this module.
1477  * This is a Mono runtime internal function.
1478  */
1479 void
1480 mono_metadata_init (void)
1481 {
1482         int i;
1483
1484         type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1485
1486         for (i = 0; i < NBUILTIN_TYPES (); ++i)
1487                 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1488 }
1489
1490 /**
1491  * mono_metadata_cleanup:
1492  *
1493  * Free all resources used by this module.
1494  * This is a Mono runtime internal function.
1495  */
1496 void
1497 mono_metadata_cleanup (void)
1498 {
1499         g_hash_table_destroy (type_cache);
1500         type_cache = NULL;
1501         g_ptr_array_free (image_sets, TRUE);
1502         image_sets = NULL;
1503 }
1504
1505 /**
1506  * mono_metadata_parse_type:
1507  * @m: metadata context
1508  * @mode: king of type that may be found at @ptr
1509  * @opt_attrs: optional attributes to store in the returned type
1510  * @ptr: pointer to the type representation
1511  * @rptr: pointer updated to match the end of the decoded stream
1512  * @transient: whenever to allocate the result from the heap or from a mempool
1513  * 
1514  * Decode a compressed type description found at @ptr in @m.
1515  * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1516  * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1517  * This function can be used to decode type descriptions in method signatures,
1518  * field signatures, locals signatures etc.
1519  *
1520  * To parse a generic type, `generic_container' points to the current class'es
1521  * (the `generic_container' field in the MonoClass) or the current generic method's
1522  * (stored in image->property_hash) generic container.
1523  * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1524  * this MonoGenericContainer.
1525  *
1526  * LOCKING: Acquires the loader lock.
1527  *
1528  * Returns: a #MonoType structure representing the decoded type.
1529  */
1530 static MonoType*
1531 mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
1532                                                                    short opt_attrs, gboolean transient, const char *ptr, const char **rptr)
1533 {
1534         MonoType *type, *cached;
1535         MonoType stype;
1536         gboolean byref = FALSE;
1537         gboolean pinned = FALSE;
1538         const char *tmp_ptr;
1539         int count = 0;
1540         gboolean found;
1541
1542         /*
1543          * According to the spec, custom modifiers should come before the byref
1544          * flag, but the IL produced by ilasm from the following signature:
1545          *   object modopt(...) &
1546          * starts with a byref flag, followed by the modifiers. (bug #49802)
1547          * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1548          * it would be better to treat byref as real type constructor instead of
1549          * a modifier...
1550          * Also, pinned should come before anything else, but some MSV++ produced
1551          * assemblies violate this (#bug 61990).
1552          */
1553
1554         /* Count the modifiers first */
1555         tmp_ptr = ptr;
1556         found = TRUE;
1557         while (found) {
1558                 switch (*tmp_ptr) {
1559                 case MONO_TYPE_PINNED:
1560                 case MONO_TYPE_BYREF:
1561                         ++tmp_ptr;
1562                         break;
1563                 case MONO_TYPE_CMOD_REQD:
1564                 case MONO_TYPE_CMOD_OPT:
1565                         count ++;
1566                         mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1567                         break;
1568                 default:
1569                         found = FALSE;
1570                 }
1571         }
1572
1573         if (count) {
1574                 int size;
1575
1576                 size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
1577                 type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size);
1578                 type->num_mods = count;
1579                 if (count > 64)
1580                         g_warning ("got more than 64 modifiers in type");
1581         } else {
1582                 type = &stype;
1583                 memset (type, 0, MONO_SIZEOF_TYPE);
1584         }
1585
1586         /* Parse pinned, byref and custom modifiers */
1587         found = TRUE;
1588         count = 0;
1589         while (found) {
1590                 switch (*ptr) {
1591                 case MONO_TYPE_PINNED:
1592                         pinned = TRUE;
1593                         ++ptr;
1594                         break;
1595                 case MONO_TYPE_BYREF:
1596                         byref = TRUE;
1597                         ++ptr;
1598                         break;
1599                 case MONO_TYPE_CMOD_REQD:
1600                 case MONO_TYPE_CMOD_OPT:
1601                         mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1602                         count ++;
1603                         break;
1604                 default:
1605                         found = FALSE;
1606                 }
1607         }
1608         
1609         type->attrs = opt_attrs;
1610         type->byref = byref;
1611         type->pinned = pinned ? 1 : 0;
1612
1613         if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) {
1614                 return NULL;
1615         }
1616
1617         if (rptr)
1618                 *rptr = ptr;
1619
1620         if (!type->num_mods && !transient) {
1621                 /* no need to free type here, because it is on the stack */
1622                 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1623                         MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1624
1625                         /* Consider the case:
1626
1627                              class Foo<T> { class Bar {} }
1628                              class Test : Foo<Test>.Bar {}
1629
1630                            When Foo<Test> is being expanded, 'Test' isn't yet initialized.  It's actually in
1631                            a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1632
1633                            We ensure that the MonoClass is in a state that we can canonicalize to:
1634
1635                              klass->byval_arg.data.klass == klass
1636                              klass->this_arg.data.klass == klass
1637
1638                            If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1639
1640                            LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1641                                     of a MonoClass which currently holds the loader lock.  'type' is local.
1642                         */
1643                         if (ret->data.klass == type->data.klass) {
1644                                 return ret;
1645                         }
1646                 }
1647                 /* No need to use locking since nobody is modifying the hash table */
1648                 if ((cached = g_hash_table_lookup (type_cache, type))) {
1649                         return cached;
1650                 }
1651         }
1652         
1653         /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1654         
1655         if (type == &stype) {
1656                 type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE);
1657                 memcpy (type, &stype, MONO_SIZEOF_TYPE);
1658         }
1659         return type;
1660 }
1661
1662 MonoType*
1663 mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
1664                                                            short opt_attrs, const char *ptr, const char **rptr)
1665 {
1666         return mono_metadata_parse_type_internal (m, container, mode, opt_attrs, FALSE, ptr, rptr);
1667 }
1668
1669 /*
1670  * LOCKING: Acquires the loader lock.
1671  */
1672 MonoType*
1673 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1674                           const char *ptr, const char **rptr)
1675 {
1676         return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
1677 }
1678
1679 gboolean
1680 mono_metadata_method_has_param_attrs (MonoImage *m, int def)
1681 {
1682         MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1683         MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1684         guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1685
1686         if (def < methodt->rows)
1687                 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1688         else
1689                 lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
1690
1691         for (i = param_index; i < lastp; ++i) {
1692                 guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
1693                 if (flags)
1694                         return TRUE;
1695         }
1696
1697         return FALSE;
1698 }
1699
1700 /*
1701  * mono_metadata_get_param_attrs:
1702  *
1703  * @m The image to loader parameter attributes from
1704  * @def method def token (one based)
1705  * @param_count number of params to decode including the return value
1706  *
1707  *   Return the parameter attributes for the method whose MethodDef index is DEF. The 
1708  * returned memory needs to be freed by the caller. If all the param attributes are
1709  * 0, then NULL is returned.
1710  */
1711 int*
1712 mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
1713 {
1714         MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1715         MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1716         guint32 cols [MONO_PARAM_SIZE];
1717         guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1718         int *pattrs = NULL;
1719
1720         if (def < methodt->rows)
1721                 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1722         else
1723                 lastp = paramt->rows + 1;
1724
1725         for (i = param_index; i < lastp; ++i) {
1726                 mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1727                 if (cols [MONO_PARAM_FLAGS]) {
1728                         if (!pattrs)
1729                                 pattrs = g_new0 (int, param_count);
1730                         /* at runtime we just ignore this kind of malformed file:
1731                         * the verifier can signal the error to the user
1732                         */
1733                         if (cols [MONO_PARAM_SEQUENCE] >= param_count)
1734                                 continue;
1735                         pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1736                 }
1737         }
1738
1739         return pattrs;
1740 }
1741
1742 /*
1743  * mono_metadata_parse_signature_full:
1744  * @image: metadata context
1745  * @generic_container: generic container
1746  * @toke: metadata token
1747  *
1748  * Decode a method signature stored in the STANDALONESIG table
1749  *
1750  * LOCKING: Assumes the loader lock is held.
1751  *
1752  * Returns: a MonoMethodSignature describing the signature.
1753  */
1754 MonoMethodSignature*
1755 mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
1756 {
1757         MonoTableInfo *tables = image->tables;
1758         guint32 idx = mono_metadata_token_index (token);
1759         guint32 sig;
1760         const char *ptr;
1761
1762         if (image->dynamic)
1763                 return mono_lookup_dynamic_token (image, token, NULL);
1764
1765         g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1766                 
1767         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1768
1769         ptr = mono_metadata_blob_heap (image, sig);
1770         mono_metadata_decode_blob_size (ptr, &ptr);
1771
1772         return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL); 
1773 }
1774
1775 /*
1776  * mono_metadata_parse_signature:
1777  * @image: metadata context
1778  * @toke: metadata token
1779  *
1780  * Decode a method signature stored in the STANDALONESIG table
1781  *
1782  * Returns: a MonoMethodSignature describing the signature.
1783  */
1784 MonoMethodSignature*
1785 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1786 {
1787         return mono_metadata_parse_signature_full (image, NULL, token);
1788 }
1789
1790 /*
1791  * mono_metadata_signature_alloc:
1792  * @image: metadata context
1793  * @nparmas: number of parameters in the signature
1794  *
1795  * Allocate a MonoMethodSignature structure with the specified number of params.
1796  * The return type and the params types need to be filled later.
1797  * This is a Mono runtime internal function.
1798  *
1799  * LOCKING: Assumes the loader lock is held.
1800  *
1801  * Returns: the new MonoMethodSignature structure.
1802  */
1803 MonoMethodSignature*
1804 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1805 {
1806         MonoMethodSignature *sig;
1807
1808         sig = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
1809         sig->param_count = nparams;
1810         sig->sentinelpos = -1;
1811
1812         return sig;
1813 }
1814
1815 static MonoMethodSignature*
1816 mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
1817 {
1818         int sigsize;
1819         MonoMethodSignature *ret;
1820         sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
1821
1822         if (image) {
1823                 ret = mono_image_alloc (image, sigsize);
1824         } else if (mp) {
1825                 ret = mono_mempool_alloc (mp, sigsize);
1826         } else {
1827                 ret = g_malloc (sigsize);
1828         }
1829         memcpy (ret, sig, sigsize);
1830         return ret;
1831 }
1832
1833 MonoMethodSignature*
1834 mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
1835 {
1836         return mono_metadata_signature_dup_internal (image, NULL, sig);
1837 }
1838
1839 /*The mempool is accessed without synchronization*/
1840 MonoMethodSignature*
1841 mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
1842 {
1843         return mono_metadata_signature_dup_internal (NULL, mp, sig);
1844 }
1845
1846 /*
1847  * mono_metadata_signature_dup:
1848  * @sig: method signature
1849  *
1850  * Duplicate an existing MonoMethodSignature so it can be modified.
1851  * This is a Mono runtime internal function.
1852  *
1853  * Returns: the new MonoMethodSignature structure.
1854  */
1855 MonoMethodSignature*
1856 mono_metadata_signature_dup (MonoMethodSignature *sig)
1857 {
1858         return mono_metadata_signature_dup_full (NULL, sig);
1859 }
1860
1861 /*
1862  * mono_metadata_signature_size:
1863  *
1864  *   Return the amount of memory allocated to SIG.
1865  */
1866 guint32
1867 mono_metadata_signature_size (MonoMethodSignature *sig)
1868 {
1869         return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
1870 }
1871
1872 /*
1873  * mono_metadata_parse_method_signature:
1874  * @m: metadata context
1875  * @generic_container: generics container
1876  * @def: the MethodDef index or 0 for Ref signatures.
1877  * @ptr: pointer to the signature metadata representation
1878  * @rptr: pointer updated to match the end of the decoded stream
1879  *
1880  * Decode a method signature stored at @ptr.
1881  * This is a Mono runtime internal function.
1882  *
1883  * LOCKING: Assumes the loader lock is held.
1884  *
1885  * Returns: a MonoMethodSignature describing the signature.
1886  */
1887 MonoMethodSignature *
1888 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
1889                                            int def, const char *ptr, const char **rptr)
1890 {
1891         MonoMethodSignature *method;
1892         int i, *pattrs = NULL;
1893         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1894         guint32 gen_param_count = 0;
1895         gboolean is_open = FALSE;
1896
1897         if (*ptr & 0x10)
1898                 gen_param_count = 1;
1899         if (*ptr & 0x20)
1900                 hasthis = 1;
1901         if (*ptr & 0x40)
1902                 explicit_this = 1;
1903         call_convention = *ptr & 0x0F;
1904         ptr++;
1905         if (gen_param_count)
1906                 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
1907         param_count = mono_metadata_decode_value (ptr, &ptr);
1908
1909         if (def)
1910                 pattrs = mono_metadata_get_param_attrs (m, def, param_count + 1); /*Must be + 1 since signature's param count doesn't account for the return value */
1911
1912         method = mono_metadata_signature_alloc (m, param_count);
1913         method->hasthis = hasthis;
1914         method->explicit_this = explicit_this;
1915         method->call_convention = call_convention;
1916         method->generic_param_count = gen_param_count;
1917
1918         if (call_convention != 0xa) {
1919                 method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr);
1920                 if (!method->ret) {
1921                         mono_metadata_free_method_signature (method);
1922                         g_free (pattrs);
1923                         return NULL;
1924                 }
1925                 is_open = mono_class_is_open_constructed_type (method->ret);
1926         }
1927
1928         for (i = 0; i < method->param_count; ++i) {
1929                 if (*ptr == MONO_TYPE_SENTINEL) {
1930                         if (method->call_convention != MONO_CALL_VARARG || def) {
1931                                 g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
1932                                 g_free (pattrs);
1933                                 return NULL;
1934                         }
1935                         if (method->sentinelpos >= 0) {
1936                                 g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
1937                                 g_free (pattrs);
1938                                 return NULL;
1939                         }
1940                         method->sentinelpos = i;
1941                         ptr++;
1942                 }
1943                 method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
1944                 if (!method->params [i]) {
1945                         mono_metadata_free_method_signature (method);
1946                         g_free (pattrs);
1947                         return NULL;
1948                 }
1949                 if (!is_open)
1950                         is_open = mono_class_is_open_constructed_type (method->params [i]);
1951         }
1952
1953         /* The sentinel could be missing if the caller does not pass any additional arguments */
1954         if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
1955                 method->sentinelpos = method->param_count;
1956
1957         method->has_type_parameters = is_open;
1958
1959         if (def && (method->call_convention == MONO_CALL_VARARG))
1960                 method->sentinelpos = method->param_count;
1961
1962         g_free (pattrs);
1963
1964         if (rptr)
1965                 *rptr = ptr;
1966         /*
1967          * Add signature to a cache and increase ref count...
1968          */
1969
1970         return method;
1971 }
1972
1973 /*
1974  * mono_metadata_parse_method_signature:
1975  * @m: metadata context
1976  * @def: the MethodDef index or 0 for Ref signatures.
1977  * @ptr: pointer to the signature metadata representation
1978  * @rptr: pointer updated to match the end of the decoded stream
1979  *
1980  * Decode a method signature stored at @ptr.
1981  * This is a Mono runtime internal function.
1982  *
1983  * LOCKING: Assumes the loader lock is held.
1984  *
1985  * Returns: a MonoMethodSignature describing the signature.
1986  */
1987 MonoMethodSignature *
1988 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
1989 {
1990         return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
1991 }
1992
1993 /*
1994  * mono_metadata_free_method_signature:
1995  * @sig: signature to destroy
1996  *
1997  * Free the memory allocated in the signature @sig.
1998  * This method needs to be robust and work also on partially-built
1999  * signatures, so it does extra checks.
2000  */
2001 void
2002 mono_metadata_free_method_signature (MonoMethodSignature *sig)
2003 {
2004         /* Everything is allocated from mempools */
2005         /*
2006         int i;
2007         if (sig->ret)
2008                 mono_metadata_free_type (sig->ret);
2009         for (i = 0; i < sig->param_count; ++i) {
2010                 if (sig->params [i])
2011                         mono_metadata_free_type (sig->params [i]);
2012         }
2013         */
2014 }
2015
2016 void
2017 mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
2018 {
2019         int i;
2020
2021         /* Allocated in inflate_generic_signature () */
2022         if (sig->ret)
2023                 mono_metadata_free_type (sig->ret);
2024         for (i = 0; i < sig->param_count; ++i) {
2025                 if (sig->params [i])
2026                         mono_metadata_free_type (sig->params [i]);
2027         }
2028         g_free (sig);
2029 }
2030
2031 static gboolean
2032 inflated_method_equal (gconstpointer a, gconstpointer b)
2033 {
2034         const MonoMethodInflated *ma = a;
2035         const MonoMethodInflated *mb = b;
2036         if (ma->declaring != mb->declaring)
2037                 return FALSE;
2038         if (ma->method.method.is_mb_open != mb->method.method.is_mb_open)
2039                 return FALSE;
2040         return mono_metadata_generic_context_equal (&ma->context, &mb->context);
2041 }
2042
2043 static guint
2044 inflated_method_hash (gconstpointer a)
2045 {
2046         const MonoMethodInflated *ma = a;
2047         return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)) + ma->method.method.is_mb_open;
2048 }
2049
2050 static gboolean
2051 inflated_signature_equal (gconstpointer a, gconstpointer b)
2052 {
2053         const MonoInflatedMethodSignature *sig1 = a;
2054         const MonoInflatedMethodSignature *sig2 = b;
2055
2056         /* sig->sig is assumed to be canonized */
2057         if (sig1->sig != sig2->sig)
2058                 return FALSE;
2059         /* The generic instances are canonized */
2060         return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
2061 }
2062
2063 static guint
2064 inflated_signature_hash (gconstpointer a)
2065 {
2066         const MonoInflatedMethodSignature *sig = a;
2067
2068         /* sig->sig is assumed to be canonized */
2069         return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
2070 }
2071
2072 /*static void
2073 dump_ginst (MonoGenericInst *ginst)
2074 {
2075         int i;
2076         char *name;
2077
2078         g_print ("Ginst: <");
2079         for (i = 0; i < ginst->type_argc; ++i) {
2080                 if (i != 0)
2081                         g_print (", ");
2082                 name = mono_type_get_name (ginst->type_argv [i]);
2083                 g_print ("%s", name);
2084                 g_free (name);
2085         }
2086         g_print (">");
2087 }*/
2088
2089 static gboolean type_in_image (MonoType *type, MonoImage *image);
2090
2091 static gboolean
2092 signature_in_image (MonoMethodSignature *sig, MonoImage *image)
2093 {
2094         gpointer iter = NULL;
2095         MonoType *p;
2096
2097         while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2098                 if (type_in_image (p, image))
2099                         return TRUE;
2100
2101         return type_in_image (mono_signature_get_return_type (sig), image);
2102 }
2103
2104 static gboolean
2105 ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
2106 {
2107         int i;
2108
2109         for (i = 0; i < ginst->type_argc; ++i) {
2110                 if (type_in_image (ginst->type_argv [i], image))
2111                         return TRUE;
2112         }
2113
2114         return FALSE;
2115 }
2116
2117 static gboolean
2118 gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
2119 {
2120         return gclass->container_class->image == image ||
2121                 ginst_in_image (gclass->context.class_inst, image);
2122 }
2123
2124 static gboolean
2125 type_in_image (MonoType *type, MonoImage *image)
2126 {
2127 retry:
2128         switch (type->type) {
2129         case MONO_TYPE_GENERICINST:
2130                 return gclass_in_image (type->data.generic_class, image);
2131         case MONO_TYPE_PTR:
2132                 type = type->data.type;
2133                 goto retry;
2134         case MONO_TYPE_SZARRAY:
2135                 type = &type->data.klass->byval_arg;
2136                 goto retry;
2137         case MONO_TYPE_ARRAY:
2138                 type = &type->data.array->eklass->byval_arg;
2139                 goto retry;
2140         case MONO_TYPE_FNPTR:
2141                 return signature_in_image (type->data.method, image);
2142         case MONO_TYPE_VAR: {
2143                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2144                 if (container) {
2145                         g_assert (!container->is_method);
2146                         /*
2147                          * FIXME: The following check is here solely
2148                          * for monodis, which uses the internal
2149                          * function
2150                          * mono_metadata_load_generic_params().  The
2151                          * caller of that function needs to fill in
2152                          * owner->klass or owner->method of the
2153                          * returned struct, but monodis doesn't do
2154                          * that.  The image unloading depends on that,
2155                          * however, so a crash results without this
2156                          * check.
2157                          */
2158                         if (!container->owner.klass)
2159                                 return container->image == image;
2160                         return container->owner.klass->image == image;
2161                 } else {
2162                         return type->data.generic_param->image == image;
2163                 }
2164         }
2165         case MONO_TYPE_MVAR: {
2166                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2167                 if (type->data.generic_param->image == image)
2168                         return TRUE;
2169                 if (container) {
2170                         g_assert (container->is_method);
2171                         if (!container->owner.method)
2172                                 /* RefEmit created generic param whose method is not finished */
2173                                 return container->image == image;
2174                         return container->owner.method->klass->image == image;
2175                 } else {
2176                         return type->data.generic_param->image == image;
2177                 }
2178         }
2179         default:
2180                 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2181                 return image == mono_class_from_mono_type (type)->image;
2182         }
2183 }
2184
2185 /*
2186  * get_image_set:
2187  *
2188  *   Return a MonoImageSet representing the set of images in IMAGES.
2189  * 
2190  * LOCKING: Assumes the loader lock is held.
2191  */
2192 static MonoImageSet*
2193 get_image_set (MonoImage **images, int nimages)
2194 {
2195         int i, j, k;
2196         MonoImageSet *set;
2197         GSList *l;
2198
2199         if (!image_sets)
2200                 image_sets = g_ptr_array_new ();
2201
2202         /* Common case */
2203         if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
2204                 return mscorlib_image_set;
2205
2206         /* Happens with empty generic instances */
2207         if (nimages == 0)
2208                 return mscorlib_image_set;
2209
2210         if (images [0] == mono_defaults.corlib && nimages > 1)
2211                 l = images [1]->image_sets;
2212         else
2213                 l = images [0]->image_sets;
2214
2215         set = NULL;
2216         for (; l; l = l->next) {
2217                 set = l->data;
2218
2219                 if (set->nimages == nimages) {
2220                         for (j = 0; j < nimages; ++j) {
2221                                 for (k = 0; k < nimages; ++k)
2222                                         if (set->images [k] == images [j])
2223                                                 break;
2224                                 if (k == nimages)
2225                                         /* Not found */
2226                                         break;
2227                         }
2228                         if (j == nimages)
2229                                 /* Found */
2230                                 break;
2231                 }
2232         }
2233
2234         if (!l) {
2235                 /* Not found */
2236                 set = g_new0 (MonoImageSet, 1);
2237                 set->nimages = nimages;
2238                 set->images = g_new0 (MonoImage*, nimages);
2239                 InitializeCriticalSection (&set->lock);
2240                 for (i = 0; i < nimages; ++i)
2241                         set->images [i] = images [i];
2242                 set->gclass_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
2243                 set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
2244                 set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
2245                 set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
2246         
2247                 for (i = 0; i < nimages; ++i)
2248                         set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
2249
2250                 g_ptr_array_add (image_sets, set);
2251         }
2252
2253         if (nimages == 1 && images [0] == mono_defaults.corlib)
2254                 mscorlib_image_set = set;
2255
2256         return set;
2257 }
2258
2259 static void
2260 delete_image_set (MonoImageSet *set)
2261 {
2262         int i;
2263
2264         g_hash_table_destroy (set->gclass_cache);
2265         g_hash_table_destroy (set->ginst_cache);
2266         g_hash_table_destroy (set->gmethod_cache);
2267         g_hash_table_destroy (set->gsignature_cache);
2268
2269         for (i = 0; i < set->nimages; ++i)
2270                 set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
2271
2272         g_ptr_array_remove (image_sets, set);
2273
2274         if (set->mempool)
2275                 mono_mempool_destroy (set->mempool);
2276         g_free (set->images);
2277         DeleteCriticalSection (&set->lock);
2278         g_free (set);
2279 }
2280
2281 /* 
2282  * Structure used by the collect_..._images functions to store the image list.
2283  */
2284 typedef struct {
2285         MonoImage *image_buf [64];
2286         MonoImage **images;
2287         int nimages, images_len;
2288 } CollectData;
2289
2290 static void
2291 collect_data_init (CollectData *data)
2292 {
2293         data->images = data->image_buf;
2294         data->images_len = 64;
2295         data->nimages = 0;
2296 }
2297
2298 static void
2299 collect_data_free (CollectData *data)
2300 {
2301         if (data->images != data->image_buf)
2302                 g_free (data->images);
2303 }
2304
2305 static void
2306 enlarge_data (CollectData *data)
2307 {
2308         int new_len = data->images_len < 16 ? 16 : data->images_len * 2;
2309         MonoImage **d = g_new (MonoImage *, new_len);
2310
2311         // FIXME: test this
2312         g_assert_not_reached ();
2313         memcpy (d, data->images, data->images_len);
2314         if (data->images != data->image_buf)
2315                 g_free (data->images);
2316         data->images = d;
2317         data->images_len = new_len;
2318 }
2319
2320 static inline void
2321 add_image (MonoImage *image, CollectData *data)
2322 {
2323         int i;
2324
2325         /* The arrays are small, so use a linear search instead of a hash table */
2326         for (i = 0; i < data->nimages; ++i)
2327                 if (data->images [i] == image)
2328                         return;
2329
2330         if (data->nimages == data->images_len)
2331                 enlarge_data (data);
2332
2333         data->images [data->nimages ++] = image;
2334 }
2335
2336 static void
2337 collect_type_images (MonoType *type, CollectData *data);
2338
2339 static void
2340 collect_ginst_images (MonoGenericInst *ginst, CollectData *data)
2341 {
2342         int i;
2343
2344         for (i = 0; i < ginst->type_argc; ++i) {
2345                 collect_type_images (ginst->type_argv [i], data);
2346         }
2347 }
2348
2349 static void
2350 collect_gclass_images (MonoGenericClass *gclass, CollectData *data)
2351 {
2352         add_image (gclass->container_class->image, data);
2353         if (gclass->context.class_inst)
2354                 collect_ginst_images (gclass->context.class_inst, data);
2355 }
2356
2357 static void
2358 collect_signature_images (MonoMethodSignature *sig, CollectData *data)
2359 {
2360         gpointer iter = NULL;
2361         MonoType *p;
2362
2363         collect_type_images (mono_signature_get_return_type (sig), data);
2364         while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2365                 collect_type_images (p, data);
2366 }
2367
2368 static void
2369 collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData *data)
2370 {
2371         collect_signature_images (sig->sig, data);
2372         if (sig->context.class_inst)
2373                 collect_ginst_images (sig->context.class_inst, data);
2374         if (sig->context.method_inst)
2375                 collect_ginst_images (sig->context.method_inst, data);
2376 }
2377
2378 static void
2379 collect_method_images (MonoMethodInflated *method, CollectData *data)
2380 {
2381         add_image (method->declaring->klass->image, data);
2382         if (method->context.class_inst)
2383                 collect_ginst_images (method->context.class_inst, data);
2384         if (method->context.method_inst)
2385                 collect_ginst_images (method->context.method_inst, data);
2386         /*
2387         if (((MonoMethod*)method)->signature)
2388                 collect_signature_images (mono_method_signature ((MonoMethod*)method), data);
2389         */
2390 }
2391
2392 static void
2393 collect_type_images (MonoType *type, CollectData *data)
2394 {
2395 retry:
2396         switch (type->type) {
2397         case MONO_TYPE_GENERICINST:
2398                 collect_gclass_images (type->data.generic_class, data);
2399                 break;
2400         case MONO_TYPE_PTR:
2401                 type = type->data.type;
2402                 goto retry;
2403         case MONO_TYPE_SZARRAY:
2404                 type = &type->data.klass->byval_arg;
2405                 goto retry;
2406         case MONO_TYPE_ARRAY:
2407                 type = &type->data.array->eklass->byval_arg;
2408                 goto retry;
2409         case MONO_TYPE_FNPTR:
2410                 //return signature_in_image (type->data.method, image);
2411                 g_assert_not_reached ();
2412         case MONO_TYPE_VAR: {
2413                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2414                 if (container) {
2415                         g_assert (!container->is_method);
2416                         /*
2417                          * FIXME: The following check is here solely
2418                          * for monodis, which uses the internal
2419                          * function
2420                          * mono_metadata_load_generic_params().  The
2421                          * caller of that function needs to fill in
2422                          * owner->klass or owner->method of the
2423                          * returned struct, but monodis doesn't do
2424                          * that.  The image unloading depends on that,
2425                          * however, so a crash results without this
2426                          * check.
2427                          */
2428                         if (!container->owner.klass)
2429                                 add_image (container->image, data);
2430                         else
2431                                 add_image (container->owner.klass->image, data);
2432                 } else {
2433                         add_image (type->data.generic_param->image, data);
2434                 }
2435         }
2436                 break;
2437         case MONO_TYPE_MVAR: {
2438                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2439                 if (type->data.generic_param->image)
2440                         add_image (type->data.generic_param->image, data);
2441                 if (container) {
2442                         if (!container->owner.method) {
2443                                 /* RefEmit created generic param whose method is not finished */
2444                                 add_image (container->image, data);
2445                         } else {
2446                                 g_assert (container->is_method);
2447                                 add_image (container->owner.method->klass->image, data);
2448                         }
2449                 } else {
2450                         add_image (type->data.generic_param->image, data);
2451                 }
2452         }
2453                 break;
2454         case MONO_TYPE_CLASS:
2455         case MONO_TYPE_VALUETYPE:
2456                 add_image (mono_class_from_mono_type (type)->image, data);
2457                 break;
2458         default:
2459                 add_image (mono_defaults.corlib, data);
2460         }
2461 }
2462
2463 typedef struct {
2464         MonoImage *image;
2465         GSList *list;
2466 } CleanForImageUserData;
2467
2468 static gboolean
2469 steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
2470 {
2471         MonoGenericClass *gclass = key;
2472         CleanForImageUserData *user_data = data;
2473
2474         g_assert (gclass_in_image (gclass, user_data->image));
2475
2476         user_data->list = g_slist_prepend (user_data->list, gclass);
2477         return TRUE;
2478 }
2479
2480 static gboolean
2481 steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
2482 {
2483         MonoGenericInst *ginst = key;
2484         CleanForImageUserData *user_data = data;
2485
2486         // This doesn't work during corlib compilation
2487         //g_assert (ginst_in_image (ginst, user_data->image));
2488
2489         user_data->list = g_slist_prepend (user_data->list, ginst);
2490         return TRUE;
2491 }
2492
2493 static gboolean
2494 inflated_method_in_image (gpointer key, gpointer value, gpointer data)
2495 {
2496         MonoImage *image = data;
2497         MonoMethodInflated *method = key;
2498
2499         // FIXME:
2500         // https://bugzilla.novell.com/show_bug.cgi?id=458168
2501         g_assert (method->declaring->klass->image == image ||
2502                 (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
2503                           (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image)));
2504
2505         return TRUE;
2506 }
2507
2508 static gboolean
2509 inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
2510 {
2511         MonoImage *image = data;
2512         MonoInflatedMethodSignature *sig = key;
2513
2514         return signature_in_image (sig->sig, image) ||
2515                 (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
2516                 (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
2517 }       
2518
2519 static void
2520 check_gmethod (gpointer key, gpointer value, gpointer data)
2521 {
2522         MonoMethodInflated *method = key;
2523         MonoImage *image = data;
2524
2525         if (method->context.class_inst)
2526                 g_assert (!ginst_in_image (method->context.class_inst, image));
2527         if (method->context.method_inst)
2528                 g_assert (!ginst_in_image (method->context.method_inst, image));
2529         if (((MonoMethod*)method)->signature)
2530                 g_assert (!signature_in_image (mono_method_signature ((MonoMethod*)method), image));
2531 }
2532
2533 /*
2534  * check_image_sets:
2535  *
2536  *   Run a consistency check on the image set data structures.
2537  */
2538 static G_GNUC_UNUSED void
2539 check_image_sets (MonoImage *image)
2540 {
2541         int i;
2542         GSList *l = image->image_sets;
2543
2544         if (!image_sets)
2545                 return;
2546
2547         for (i = 0; i < image_sets->len; ++i) {
2548                 MonoImageSet *set = g_ptr_array_index (image_sets, i);
2549
2550                 if (!g_slist_find (l, set)) {
2551                         g_hash_table_foreach (set->gmethod_cache, check_gmethod, image);
2552                 }
2553         }
2554 }
2555
2556 GSList*
2557 mono_metadata_clean_for_image (MonoImage *image)
2558 {
2559         CleanForImageUserData ginst_data, gclass_data;
2560         GSList *l, *set_list, *free_list = NULL;
2561
2562         //check_image_sets (image);
2563
2564         /* The data structures could reference each other so we delete them in two phases */
2565         ginst_data.image = gclass_data.image = image;
2566         ginst_data.list = gclass_data.list = NULL;
2567         mono_loader_lock ();
2568
2569         /* Collect the items to delete */
2570         /* delete_image_set () modifies the lists so make a copy */
2571         for (l = image->image_sets; l; l = l->next) {
2572                 MonoImageSet *set = l->data;
2573
2574                 g_hash_table_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
2575                 g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
2576                 g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
2577                 g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
2578         }
2579
2580         /* Delete the removed items */
2581         for (l = ginst_data.list; l; l = l->next)
2582                 free_list = g_slist_concat (free_generic_inst_dependents (l->data), free_list);
2583         for (l = gclass_data.list; l; l = l->next)
2584                 free_list = g_slist_concat (free_generic_class_dependents (l->data), free_list);
2585         g_slist_free (ginst_data.list);
2586         g_slist_free (gclass_data.list);
2587         /* delete_image_set () modifies the lists so make a copy */
2588         set_list = g_slist_copy (image->image_sets);
2589         for (l = set_list; l; l = l->next) {
2590                 MonoImageSet *set = l->data;
2591
2592                 delete_image_set (set);
2593         }
2594         g_slist_free (set_list);
2595
2596         mono_loader_unlock ();
2597
2598         return free_list;
2599 }
2600
2601 static void
2602 free_inflated_method (MonoMethodInflated *imethod)
2603 {
2604         int i;
2605         MonoMethod *method = (MonoMethod*)imethod;
2606
2607         mono_marshal_free_inflated_wrappers (method);
2608
2609         if (method->signature)
2610                 mono_metadata_free_inflated_signature (method->signature);
2611
2612         if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
2613                 MonoMethodHeader *header = imethod->header;
2614
2615                 if (header) {
2616                         /* Allocated in inflate_generic_header () */
2617                         for (i = 0; i < header->num_locals; ++i)
2618                                 mono_metadata_free_type (header->locals [i]);
2619                         g_free (header->clauses);
2620                         g_free (header);
2621                 }
2622         }
2623
2624         g_free (method);
2625 }
2626
2627 static void
2628 free_list_with_data (GSList *l)
2629 {
2630         while (l) {
2631                 g_free (l->data);
2632                 l = g_slist_delete_link (l, l);
2633         }
2634 }
2635
2636 static GSList*
2637 free_generic_inst_dependents (MonoGenericInst *ginst)
2638 {
2639         int i;
2640
2641         for (i = 0; i < ginst->type_argc; ++i)
2642                 mono_metadata_free_type (ginst->type_argv [i]);
2643         return g_slist_prepend (NULL, ginst);
2644 }
2645
2646 static void
2647 free_generic_inst (MonoGenericInst *ginst)
2648 {
2649         free_list_with_data (free_generic_inst_dependents (ginst));
2650 }
2651
2652 static GSList*
2653 free_generic_class_dependents (MonoGenericClass *gclass)
2654 {
2655         GSList *l = NULL;
2656         int i;
2657
2658         /* FIXME: The dynamic case */
2659         if (gclass->cached_class && !gclass->cached_class->image->dynamic && !mono_generic_class_is_generic_type_definition (gclass)) {
2660                 MonoClass *class = gclass->cached_class;
2661
2662                 /* Allocated in mono_class_init () */
2663                 g_free (class->methods);
2664                 if (class->ext) {
2665                         g_free (class->ext->properties);
2666                         g_free (class->ext->field_def_values);
2667                 }
2668                 /* Allocated in mono_class_setup_fields () */
2669                 g_free (class->fields);
2670                 /* Allocated in mono_class_setup_vtable_general () */
2671                 g_free (class->vtable);
2672                 /* Allocated in mono_generic_class_get_class () */
2673                 g_free (class->interfaces);
2674                 /* Allocated in setup_interface_offsets () */
2675                 g_free (class->interfaces_packed);
2676                 g_free (class->interface_offsets_packed);
2677                 g_free (class->interface_bitmap);
2678                 /* Allocated in mono_class_setup_supertypes () */
2679                 g_free (class->supertypes);
2680                 l = g_slist_prepend (l, class);
2681         } else if (gclass->is_dynamic) {
2682                 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass;
2683
2684                 for (i = 0; i < dgclass->count_fields; ++i) {
2685                         MonoClassField *field = dgclass->fields + i;
2686                         mono_metadata_free_type (field->type);
2687                         g_free ((char*)field->name);
2688 #if HAVE_SGEN_GC
2689                         MONO_GC_UNREGISTER_ROOT (dgclass->field_objects [i]);
2690 #endif
2691                 }
2692
2693                 g_free (dgclass->methods);
2694                 g_free (dgclass->ctors);
2695                 g_free (dgclass->fields);
2696                 g_free (dgclass->field_objects);
2697                 g_free (dgclass->field_generic_types);
2698                 if (!mono_generic_class_is_generic_type_definition (gclass))
2699                         l = g_slist_prepend (l, gclass->cached_class);
2700         }
2701         return g_slist_prepend (l, gclass);
2702 }
2703
2704 static void
2705 free_generic_class (MonoGenericClass *gclass)
2706 {
2707         free_list_with_data (free_generic_class_dependents (gclass));
2708 }
2709
2710 static void
2711 free_inflated_signature (MonoInflatedMethodSignature *sig)
2712 {
2713         mono_metadata_free_inflated_signature (sig->sig);
2714         g_free (sig);
2715 }
2716
2717 /*
2718  * LOCKING: assumes the loader lock is held.
2719  */
2720 MonoMethodInflated*
2721 mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
2722 {
2723         CollectData data;
2724         MonoImageSet *set;
2725
2726         collect_data_init (&data);
2727
2728         collect_method_images (method, &data);
2729
2730         set = get_image_set (data.images, data.nimages);
2731
2732         collect_data_free (&data);
2733
2734         if (cache) {
2735                 g_hash_table_insert (set->gmethod_cache, method, method);
2736
2737                 return method;
2738         } else {
2739                 return g_hash_table_lookup (set->gmethod_cache, method);
2740         }
2741 }
2742
2743 /*
2744  * mono_metadata_get_inflated_signature:
2745  *
2746  *   Given an inflated signature and a generic context, return a canonical copy of the 
2747  * signature. The returned signature might be equal to SIG or it might be a cached copy.
2748  */
2749 MonoMethodSignature *
2750 mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
2751 {
2752         MonoInflatedMethodSignature helper;
2753         MonoInflatedMethodSignature *res;
2754         CollectData data;
2755         MonoImageSet *set;
2756
2757         mono_loader_lock ();
2758
2759         helper.sig = sig;
2760         helper.context.class_inst = context->class_inst;
2761         helper.context.method_inst = context->method_inst;
2762
2763         collect_data_init (&data);
2764
2765         collect_inflated_signature_images (&helper, &data);
2766
2767         set = get_image_set (data.images, data.nimages);
2768
2769         collect_data_free (&data);
2770
2771         res = g_hash_table_lookup (set->gsignature_cache, &helper);
2772         if (!res) {
2773                 res = g_new0 (MonoInflatedMethodSignature, 1);
2774                 res->sig = sig;
2775                 res->context.class_inst = context->class_inst;
2776                 res->context.method_inst = context->method_inst;
2777                 g_hash_table_insert (set->gsignature_cache, res, res);
2778         }
2779
2780         mono_loader_unlock ();
2781         return res->sig;
2782 }
2783
2784 /*
2785  * mono_metadata_get_generic_inst:
2786  *
2787  * Given a list of types, return a MonoGenericInst that represents that list.
2788  * The returned MonoGenericInst has its own copy of the list of types.  The list
2789  * passed in the argument can be freed, modified or disposed of.
2790  *
2791  */
2792 MonoGenericInst *
2793 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
2794 {
2795         MonoGenericInst *ginst;
2796         gboolean is_open;
2797         int i;
2798         int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
2799         CollectData data;
2800         MonoImageSet *set;
2801
2802         for (i = 0; i < type_argc; ++i)
2803                 if (mono_class_is_open_constructed_type (type_argv [i]))
2804                         break;
2805         is_open = (i < type_argc);
2806
2807         ginst = alloca (size);
2808 #ifndef MONO_SMALL_CONFIG
2809         ginst->id = 0;
2810 #endif
2811         ginst->is_open = is_open;
2812         ginst->type_argc = type_argc;
2813         memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
2814
2815         mono_loader_lock ();
2816
2817         collect_data_init (&data);
2818
2819         collect_ginst_images (ginst, &data);
2820
2821         set = get_image_set (data.images, data.nimages);
2822
2823         collect_data_free (&data);
2824
2825         ginst = g_hash_table_lookup (set->ginst_cache, ginst);
2826         if (!ginst) {
2827                 ginst = g_malloc (size);
2828 #ifndef MONO_SMALL_CONFIG
2829                 ginst->id = ++next_generic_inst_id;
2830 #endif
2831                 ginst->is_open = is_open;
2832                 ginst->type_argc = type_argc;
2833
2834                 for (i = 0; i < type_argc; ++i)
2835                         ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
2836
2837                 g_hash_table_insert (set->ginst_cache, ginst, ginst);
2838         }
2839
2840         mono_loader_unlock ();
2841         return ginst;
2842 }
2843
2844 static gboolean
2845 mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
2846 {
2847         MonoGenericContainer *container = container_class->generic_container; 
2848
2849         if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
2850                 return FALSE;
2851         return inst == container->context.class_inst;
2852 }
2853
2854 /*
2855  * mono_metadata_lookup_generic_class:
2856  *
2857  * Returns a MonoGenericClass with the given properties.
2858  *
2859  */
2860 MonoGenericClass *
2861 mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
2862 {
2863         MonoGenericClass *gclass;
2864         MonoGenericClass helper;
2865         gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
2866         MonoImageSet *set;
2867         CollectData data;
2868
2869         helper.container_class = container_class;
2870         helper.context.class_inst = inst;
2871         helper.context.method_inst = NULL;
2872         helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2873         helper.is_tb_open = is_tb_open;
2874         helper.cached_class = NULL;
2875
2876         mono_loader_lock ();
2877
2878         collect_data_init (&data);
2879
2880         collect_gclass_images (&helper, &data);
2881
2882         set = get_image_set (data.images, data.nimages);
2883
2884         collect_data_free (&data);
2885
2886         gclass = g_hash_table_lookup (set->gclass_cache, &helper);
2887
2888         /* A tripwire just to keep us honest */
2889         g_assert (!helper.cached_class);
2890
2891         if (gclass) {
2892                 mono_loader_unlock ();
2893                 return gclass;
2894         }
2895
2896         if (is_dynamic) {
2897                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
2898                 gclass = &dgclass->generic_class;
2899                 gclass->is_dynamic = 1;
2900         } else {
2901                 gclass = g_new0 (MonoGenericClass, 1);
2902         }
2903
2904         gclass->is_tb_open = is_tb_open;
2905         gclass->container_class = container_class;
2906         gclass->context.class_inst = inst;
2907         gclass->context.method_inst = NULL;
2908         if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
2909                 gclass->cached_class = container_class;
2910
2911         g_hash_table_insert (set->gclass_cache, gclass, gclass);
2912
2913         mono_loader_unlock ();
2914
2915         return gclass;
2916 }
2917
2918 /*
2919  * mono_metadata_inflate_generic_inst:
2920  *
2921  * Instantiate the generic instance @ginst with the context @context.
2922  * Check @error for success.
2923  *
2924  */
2925 MonoGenericInst *
2926 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
2927 {
2928         MonoType **type_argv;
2929         MonoGenericInst *nginst = NULL;
2930         int i, count = 0;
2931
2932         mono_error_init (error);
2933
2934         if (!ginst->is_open)
2935                 return ginst;
2936
2937         type_argv = g_new0 (MonoType*, ginst->type_argc);
2938
2939         for (i = 0; i < ginst->type_argc; i++) {
2940                 type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
2941                 if (!mono_error_ok (error))
2942                         goto cleanup;
2943                 ++count;
2944         }
2945
2946         nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
2947
2948 cleanup:
2949         for (i = 0; i < count; i++)
2950                 mono_metadata_free_type (type_argv [i]);
2951         g_free (type_argv);
2952
2953         return nginst;
2954 }
2955
2956 MonoGenericInst *
2957 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
2958                                   int count, const char *ptr, const char **rptr)
2959 {
2960         MonoType **type_argv;
2961         MonoGenericInst *ginst;
2962         int i;
2963
2964         type_argv = g_new0 (MonoType*, count);
2965
2966         for (i = 0; i < count; i++) {
2967                 MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
2968                 if (!t) {
2969                         g_free (type_argv);
2970                         return NULL;
2971                 }
2972                 type_argv [i] = t;
2973         }
2974
2975         if (rptr)
2976                 *rptr = ptr;
2977
2978         ginst = mono_metadata_get_generic_inst (count, type_argv);
2979
2980         g_free (type_argv);
2981
2982         return ginst;
2983 }
2984
2985 static gboolean
2986 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
2987                                       const char *ptr, const char **rptr)
2988 {
2989         MonoGenericInst *inst;
2990         MonoClass *gklass;
2991         MonoType *gtype;
2992         int count;
2993
2994         gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
2995         if (gtype == NULL)
2996                 return FALSE;
2997
2998         gklass = mono_class_from_mono_type (gtype);
2999         if (!gklass->generic_container)
3000                 return FALSE;
3001
3002         count = mono_metadata_decode_value (ptr, &ptr);
3003         inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
3004         if (inst == NULL)
3005                 return FALSE;
3006
3007         if (rptr)
3008                 *rptr = ptr;
3009
3010         type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
3011         return TRUE;
3012 }
3013
3014 /*
3015  * select_container:
3016  * @gc: The generic container to normalize
3017  * @type: The kind of generic parameters the resulting generic-container should contain
3018  */
3019
3020 static MonoGenericContainer *
3021 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
3022 {
3023         gboolean is_var = (type == MONO_TYPE_VAR);
3024         if (!gc)
3025                 return NULL;
3026
3027         g_assert (is_var || type == MONO_TYPE_MVAR);
3028
3029         if (is_var) {
3030                 if (gc->is_method || gc->parent)
3031                         /*
3032                          * The current MonoGenericContainer is a generic method -> its `parent'
3033                          * points to the containing class'es container.
3034                          */
3035                         return gc->parent;
3036         }
3037
3038         return gc;
3039 }
3040
3041 /* 
3042  * mono_metadata_parse_generic_param:
3043  * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3044  *                     see mono_metadata_parse_type_full() for details.
3045  * Internal routine to parse a generic type parameter.
3046  * LOCKING: Acquires the loader lock
3047  */
3048 static MonoGenericParam *
3049 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
3050                                    MonoTypeEnum type, const char *ptr, const char **rptr)
3051 {
3052         int index = mono_metadata_decode_value (ptr, &ptr);
3053         if (rptr)
3054                 *rptr = ptr;
3055
3056         generic_container = select_container (generic_container, type);
3057         if (!generic_container) {
3058                 /* Create dummy MonoGenericParam */
3059                 MonoGenericParam *param;
3060
3061                 param = mono_image_alloc0 (m, sizeof (MonoGenericParam));
3062                 param->num = index;
3063                 param->image = m;
3064
3065                 return param;
3066         }
3067
3068         if (index >= generic_container->type_argc)
3069                 return NULL;
3070
3071         return mono_generic_container_get_param (generic_container, index);
3072 }
3073
3074 /*
3075  * mono_metadata_get_shared_type:
3076  *
3077  *   Return a shared instance of TYPE, if available, NULL otherwise.
3078  * Shared MonoType instances help save memory. Their contents should not be modified
3079  * by the caller. They do not need to be freed as their lifetime is bound by either
3080  * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3081  * instance they are embedded in. If they are freed, they should be freed using
3082  * mono_metadata_free_type () instead of g_free ().
3083  */
3084 MonoType*
3085 mono_metadata_get_shared_type (MonoType *type)
3086 {
3087         MonoType *cached;
3088
3089         /* No need to use locking since nobody is modifying the hash table */
3090         if ((cached = g_hash_table_lookup (type_cache, type)))
3091                 return cached;
3092
3093         switch (type->type){
3094         case MONO_TYPE_CLASS:
3095         case MONO_TYPE_VALUETYPE:
3096                 if (type == &type->data.klass->byval_arg)
3097                         return type;
3098                 if (type == &type->data.klass->this_arg)
3099                         return type;
3100                 break;
3101         }
3102
3103         return NULL;
3104 }
3105
3106 /* 
3107  * do_mono_metadata_parse_type:
3108  * @type: MonoType to be filled in with the return value
3109  * @m: image context
3110  * @generic_context: generics_context
3111  * @transient: whenever to allocate data from the heap
3112  * @ptr: pointer to the encoded type
3113  * @rptr: pointer where the end of the encoded type is saved
3114  * 
3115  * Internal routine used to "fill" the contents of @type from an 
3116  * allocated pointer.  This is done this way to avoid doing too
3117  * many mini-allocations (particularly for the MonoFieldType which
3118  * most of the time is just a MonoType, but sometimes might be augmented).
3119  *
3120  * This routine is used by mono_metadata_parse_type and
3121  * mono_metadata_parse_field_type
3122  *
3123  * This extracts a Type as specified in Partition II (22.2.12) 
3124  *
3125  * Returns: FALSE if the type could not be loaded
3126  */
3127 static gboolean
3128 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3129                                                          gboolean transient, const char *ptr, const char **rptr)
3130 {
3131         gboolean ok = TRUE;
3132         type->type = mono_metadata_decode_value (ptr, &ptr);
3133         
3134         switch (type->type){
3135         case MONO_TYPE_VOID:
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_I8:
3145         case MONO_TYPE_U8:
3146         case MONO_TYPE_R4:
3147         case MONO_TYPE_R8:
3148         case MONO_TYPE_I:
3149         case MONO_TYPE_U:
3150         case MONO_TYPE_STRING:
3151         case MONO_TYPE_OBJECT:
3152         case MONO_TYPE_TYPEDBYREF:
3153                 break;
3154         case MONO_TYPE_VALUETYPE:
3155         case MONO_TYPE_CLASS: {
3156                 guint32 token;
3157                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
3158                 type->data.klass = mono_class_get (m, token);
3159                 if (!type->data.klass)
3160                         return FALSE;
3161                 break;
3162         }
3163         case MONO_TYPE_SZARRAY: {
3164                 MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
3165                 if (!etype)
3166                         return FALSE;
3167                 type->data.klass = mono_class_from_mono_type (etype);
3168                 if (!type->data.klass)
3169                         return FALSE;
3170                 break;
3171         }
3172         case MONO_TYPE_PTR:
3173                 type->data.type = mono_metadata_parse_type_internal (m, container, MONO_PARSE_MOD_TYPE, 0, transient, ptr, &ptr);
3174                 if (!type->data.type)
3175                         return FALSE;
3176                 break;
3177         case MONO_TYPE_FNPTR:
3178                 type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
3179                 if (!type->data.method)
3180                         return FALSE;
3181                 break;
3182         case MONO_TYPE_ARRAY:
3183                 type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr);
3184                 if (!type->data.array)
3185                         return FALSE;
3186                 break;
3187         case MONO_TYPE_MVAR:
3188                 if (container && !container->is_method)
3189                         return FALSE;
3190         case MONO_TYPE_VAR:
3191                 type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
3192                 if (!type->data.generic_param)
3193                         return FALSE;
3194                 break;
3195         case MONO_TYPE_GENERICINST:
3196                 ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
3197                 break;
3198         default:
3199                 g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name);
3200                 return FALSE;
3201         }
3202         
3203         if (rptr)
3204                 *rptr = ptr;
3205         return ok;
3206 }
3207
3208 /*
3209  * mono_metadata_free_type:
3210  * @type: type to free
3211  *
3212  * Free the memory allocated for type @type which is allocated on the heap.
3213  */
3214 void
3215 mono_metadata_free_type (MonoType *type)
3216 {
3217         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
3218                 return;
3219         
3220         switch (type->type){
3221         case MONO_TYPE_OBJECT:
3222         case MONO_TYPE_STRING:
3223                 if (!type->data.klass)
3224                         break;
3225                 /* fall through */
3226         case MONO_TYPE_CLASS:
3227         case MONO_TYPE_VALUETYPE:
3228                 if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
3229                         return;
3230                 break;
3231         case MONO_TYPE_PTR:
3232                 mono_metadata_free_type (type->data.type);
3233                 break;
3234         case MONO_TYPE_FNPTR:
3235                 mono_metadata_free_method_signature (type->data.method);
3236                 break;
3237         case MONO_TYPE_ARRAY:
3238                 mono_metadata_free_array (type->data.array);
3239                 break;
3240         }
3241
3242         g_free (type);
3243 }
3244
3245 #if 0
3246 static void
3247 hex_dump (const char *buffer, int base, int count)
3248 {
3249         int show_header = 1;
3250         int i;
3251
3252         if (count < 0){
3253                 count = -count;
3254                 show_header = 0;
3255         }
3256         
3257         for (i = 0; i < count; i++){
3258                 if (show_header)
3259                         if ((i % 16) == 0)
3260                                 printf ("\n0x%08x: ", (unsigned char) base + i);
3261
3262                 printf ("%02x ", (unsigned char) (buffer [i]));
3263         }
3264         fflush (stdout);
3265 }
3266 #endif
3267
3268 /** 
3269  * @ptr: Points to the beginning of the Section Data (25.3)
3270  */
3271 static MonoExceptionClause*
3272 parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
3273 {
3274         unsigned char sect_data_flags;
3275         const unsigned char *sptr;
3276         int is_fat;
3277         guint32 sect_data_len;
3278         MonoExceptionClause* clauses = NULL;
3279         
3280         while (1) {
3281                 /* align on 32-bit boundary */
3282                 sptr = ptr = dword_align (ptr); 
3283                 sect_data_flags = *ptr;
3284                 ptr++;
3285                 
3286                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
3287                 if (is_fat) {
3288                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
3289                         ptr += 3;
3290                 } else {
3291                         sect_data_len = ptr [0];
3292                         ++ptr;
3293                 }
3294                 /*
3295                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
3296                 hex_dump (sptr, 0, sect_data_len+8);
3297                 g_print ("\nheader: ");
3298                 hex_dump (sptr-4, 0, 4);
3299                 g_print ("\n");
3300                 */
3301                 
3302                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
3303                         const unsigned char *p = dword_align (ptr);
3304                         int i;
3305                         *num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
3306                         /* we could just store a pointer if we don't need to byteswap */
3307                         clauses = g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses));
3308                         for (i = 0; i < *num_clauses; ++i) {
3309                                 MonoExceptionClause *ec = &clauses [i];
3310                                 guint32 tof_value;
3311                                 if (is_fat) {
3312                                         ec->flags = read32 (p);
3313                                         ec->try_offset = read32 (p + 4);
3314                                         ec->try_len = read32 (p + 8);
3315                                         ec->handler_offset = read32 (p + 12);
3316                                         ec->handler_len = read32 (p + 16);
3317                                         tof_value = read32 (p + 20);
3318                                         p += 24;
3319                                 } else {
3320                                         ec->flags = read16 (p);
3321                                         ec->try_offset = read16 (p + 2);
3322                                         ec->try_len = *(p + 4);
3323                                         ec->handler_offset = read16 (p + 5);
3324                                         ec->handler_len = *(p + 7);
3325                                         tof_value = read32 (p + 8);
3326                                         p += 12;
3327                                 }
3328                                 if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3329                                         ec->data.filter_offset = tof_value;
3330                                 } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
3331                                         ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
3332                                 } else {
3333                                         ec->data.catch_class = NULL;
3334                                 }
3335                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3336                         }
3337
3338                 }
3339                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
3340                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
3341                 else
3342                         return clauses;
3343         }
3344 }
3345
3346 /*
3347  * mono_method_get_header_summary:
3348  * @method: The method to get the header.
3349  * @summary: Where to store the header
3350  *
3351  *
3352  * Returns: true if the header was properly decoded.
3353  */
3354 gboolean
3355 mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *summary)
3356 {
3357         int idx;
3358         guint32 rva;
3359         MonoImage* img;
3360         const char *ptr;
3361         unsigned char flags, format;
3362         guint16 fat_flags;
3363
3364         /*Only the GMD has a pointer to the metadata.*/
3365         while (method->is_inflated)
3366                 method = ((MonoMethodInflated*)method)->declaring;
3367
3368         summary->code_size = 0;
3369         summary->has_clauses = FALSE;
3370
3371         /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3372         if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3373                 return FALSE;
3374
3375         if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
3376                 MonoMethodHeader *header =  ((MonoMethodWrapper *)method)->header;
3377                 if (!header)
3378                         return FALSE;
3379                 summary->code_size = header->code_size;
3380                 summary->has_clauses = header->num_clauses > 0;
3381                 return TRUE;
3382         }
3383
3384
3385         idx = mono_metadata_token_index (method->token);
3386         img = method->klass->image;
3387         rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA);
3388
3389         /*We must run the verifier since we'll be decoding it.*/
3390         if (!mono_verifier_verify_method_header (img, rva, NULL))
3391                 return FALSE;
3392
3393         ptr = mono_image_rva_map (img, rva);
3394         g_assert (ptr);
3395
3396         flags = *(const unsigned char *)ptr;
3397         format = flags & METHOD_HEADER_FORMAT_MASK;
3398
3399         switch (format) {
3400         case METHOD_HEADER_TINY_FORMAT:
3401                 ptr++;
3402                 summary->code_size = flags >> 2;
3403                 break;
3404         case METHOD_HEADER_FAT_FORMAT:
3405                 fat_flags = read16 (ptr);
3406                 ptr += 4;
3407                 summary->code_size = read32 (ptr);
3408                 if (fat_flags & METHOD_HEADER_MORE_SECTS)
3409                         summary->has_clauses = TRUE;
3410                 break;
3411         default:
3412                 return FALSE;
3413         }
3414         return TRUE;
3415 }
3416
3417 /*
3418  * mono_metadata_parse_mh_full:
3419  * @m: metadata context
3420  * @generic_context: generics context
3421  * @ptr: pointer to the method header.
3422  *
3423  * Decode the method header at @ptr, including pointer to the IL code,
3424  * info about local variables and optional exception tables.
3425  * This is a Mono runtime internal function.
3426  *
3427  * LOCKING: Acquires the loader lock.
3428  *
3429  * Returns: a transient MonoMethodHeader allocated from the heap.
3430  */
3431 MonoMethodHeader *
3432 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
3433 {
3434         MonoMethodHeader *mh;
3435         unsigned char flags = *(const unsigned char *) ptr;
3436         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
3437         guint16 fat_flags;
3438         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
3439         const unsigned char *code;
3440         MonoExceptionClause* clauses = NULL;
3441         int hsize, num_clauses = 0;
3442         MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
3443         guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
3444
3445         g_return_val_if_fail (ptr != NULL, NULL);
3446
3447         switch (format) {
3448         case METHOD_HEADER_TINY_FORMAT:
3449                 mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER);
3450                 ptr++;
3451                 mh->max_stack = 8;
3452                 mh->is_transient = TRUE;
3453                 local_var_sig_tok = 0;
3454                 mh->code_size = flags >> 2;
3455                 mh->code = (unsigned char*)ptr;
3456                 return mh;
3457         case METHOD_HEADER_FAT_FORMAT:
3458                 fat_flags = read16 (ptr);
3459                 ptr += 2;
3460                 hsize = (fat_flags >> 12) & 0xf;
3461                 max_stack = read16 (ptr);
3462                 ptr += 2;
3463                 code_size = read32 (ptr);
3464                 ptr += 4;
3465                 local_var_sig_tok = read32 (ptr);
3466                 ptr += 4;
3467
3468                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
3469                         init_locals = 1;
3470                 else
3471                         init_locals = 0;
3472
3473                 code = (unsigned char*)ptr;
3474
3475                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
3476                         break;
3477
3478                 /*
3479                  * There are more sections
3480                  */
3481                 ptr = (char*)code + code_size;
3482                 break;
3483         default:
3484                 return NULL;
3485         }
3486
3487         if (local_var_sig_tok) {
3488                 int idx = (local_var_sig_tok & 0xffffff)-1;
3489                 if (idx >= t->rows)
3490                         return NULL;
3491                 mono_metadata_decode_row (t, idx, cols, 1);
3492
3493                 if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL))
3494                         return NULL;
3495         }
3496         if (fat_flags & METHOD_HEADER_MORE_SECTS)
3497                 clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr);
3498         if (local_var_sig_tok) {
3499                 const char *locals_ptr;
3500                 int len=0, i, bsize;
3501
3502                 locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
3503                 bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
3504                 if (*locals_ptr != 0x07)
3505                         g_warning ("wrong signature for locals blob");
3506                 locals_ptr++;
3507                 len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
3508                 mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause));
3509                 mh->num_locals = len;
3510                 for (i = 0; i < len; ++i) {
3511                         mh->locals [i] = mono_metadata_parse_type_internal (m, container,
3512                                                                                                                                 MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr);
3513                         if (!mh->locals [i]) {
3514                                 g_free (clauses);
3515                                 g_free (mh);
3516                                 return NULL;
3517                         }
3518                 }
3519         } else {
3520                 mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
3521         }
3522         mh->code = code;
3523         mh->code_size = code_size;
3524         mh->max_stack = max_stack;
3525         mh->is_transient = TRUE;
3526         mh->init_locals = init_locals;
3527         if (clauses) {
3528                 MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals];
3529                 memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause));
3530                 g_free (clauses);
3531                 mh->clauses = clausesp;
3532                 mh->num_clauses = num_clauses;
3533         }
3534         return mh;
3535 }
3536
3537 /*
3538  * mono_metadata_parse_mh:
3539  * @generic_context: generics context
3540  * @ptr: pointer to the method header.
3541  *
3542  * Decode the method header at @ptr, including pointer to the IL code,
3543  * info about local variables and optional exception tables.
3544  * This is a Mono runtime internal function.
3545  *
3546  * Returns: a MonoMethodHeader.
3547  */
3548 MonoMethodHeader *
3549 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
3550 {
3551         MonoMethodHeader *res;
3552
3553         mono_loader_lock ();
3554
3555         res = mono_metadata_parse_mh_full (m, NULL, ptr);
3556
3557         mono_loader_unlock ();
3558
3559         return res;
3560 }
3561
3562 /*
3563  * mono_metadata_free_mh:
3564  * @mh: a method header
3565  *
3566  * Free the memory allocated for the method header.
3567  */
3568 void
3569 mono_metadata_free_mh (MonoMethodHeader *mh)
3570 {
3571         int i;
3572
3573         /* If it is not transient it means it's part of a wrapper method,
3574          * or a SRE-generated method, so the lifetime in that case is
3575          * dictated by the method's own lifetime
3576          */
3577         if (mh->is_transient) {
3578                 for (i = 0; i < mh->num_locals; ++i)
3579                         mono_metadata_free_type (mh->locals [i]);
3580                 g_free (mh);
3581         }
3582 }
3583
3584 /*
3585  * mono_method_header_get_code:
3586  * @header: a MonoMethodHeader pointer
3587  * @code_size: memory location for returning the code size
3588  * @max_stack: memory location for returning the max stack
3589  *
3590  * Method header accessor to retreive info about the IL code properties:
3591  * a pointer to the IL code itself, the size of the code and the max number
3592  * of stack slots used by the code.
3593  *
3594  * Returns: pointer to the IL code represented by the method header.
3595  */
3596 const unsigned char*
3597 mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
3598 {
3599         if (code_size)
3600                 *code_size = header->code_size;
3601         if (max_stack)
3602                 *max_stack = header->max_stack;
3603         return header->code;
3604 }
3605
3606 /*
3607  * mono_method_header_get_locals:
3608  * @header: a MonoMethodHeader pointer
3609  * @num_locals: memory location for returning the number of local variables
3610  * @init_locals: memory location for returning the init_locals flag
3611  *
3612  * Method header accessor to retreive info about the local variables:
3613  * an array of local types, the number of locals and whether the locals
3614  * are supposed to be initialized to 0 on method entry
3615  *
3616  * Returns: pointer to an array of types of the local variables
3617  */
3618 MonoType**
3619 mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
3620 {
3621         if (num_locals)
3622                 *num_locals = header->num_locals;
3623         if (init_locals)
3624                 *init_locals = header->init_locals;
3625         return header->locals;
3626 }
3627
3628 /*
3629  * mono_method_header_get_num_clauses:
3630  * @header: a MonoMethodHeader pointer
3631  *
3632  * Method header accessor to retreive the number of exception clauses.
3633  *
3634  * Returns: the number of exception clauses present
3635  */
3636 int
3637 mono_method_header_get_num_clauses (MonoMethodHeader *header)
3638 {
3639         return header->num_clauses;
3640 }
3641
3642 /*
3643  * mono_method_header_get_clauses:
3644  * @header: a MonoMethodHeader pointer
3645  * @method: MonoMethod the header belongs to
3646  * @iter: pointer to a iterator
3647  * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3648  *
3649  * Get the info about the exception clauses in the method. Set *iter to NULL to
3650  * initiate the iteration, then call the method repeatedly until it returns FALSE.
3651  * At each iteration, the structure pointed to by clause if filled with the
3652  * exception clause information.
3653  *
3654  * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3655  * clauses.
3656  */
3657 int
3658 mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
3659 {
3660         MonoExceptionClause *sc;
3661         /* later we'll be able to use this interface to parse the clause info on demand,
3662          * without allocating anything.
3663          */
3664         if (!iter || !header->num_clauses)
3665                 return FALSE;
3666         if (!*iter) {
3667                 *iter = sc = header->clauses;
3668                 *clause = *sc;
3669                 return TRUE;
3670         }
3671         sc = *iter;
3672         sc++;
3673         if (sc < header->clauses + header->num_clauses) {
3674                 *iter = sc;
3675                 *clause = *sc;
3676                 return TRUE;
3677         }
3678         return FALSE;
3679 }
3680
3681 /**
3682  * mono_metadata_parse_field_type:
3683  * @m: metadata context to extract information from
3684  * @ptr: pointer to the field signature
3685  * @rptr: pointer updated to match the end of the decoded stream
3686  *
3687  * Parses the field signature, and returns the type information for it. 
3688  *
3689  * Returns: The MonoType that was extracted from @ptr.
3690  */
3691 MonoType *
3692 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
3693 {
3694         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
3695 }
3696
3697 /**
3698  * mono_metadata_parse_param:
3699  * @m: metadata context to extract information from
3700  * @ptr: pointer to the param signature
3701  * @rptr: pointer updated to match the end of the decoded stream
3702  *
3703  * Parses the param signature, and returns the type information for it. 
3704  *
3705  * Returns: The MonoType that was extracted from @ptr.
3706  */
3707 MonoType *
3708 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
3709 {
3710         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
3711 }
3712
3713 /*
3714  * mono_metadata_token_from_dor:
3715  * @dor_token: A TypeDefOrRef coded index
3716  *
3717  * dor_token is a TypeDefOrRef coded index: it contains either
3718  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3719  * bits contain an index into the table.
3720  *
3721  * Returns: an expanded token
3722  */
3723 guint32
3724 mono_metadata_token_from_dor (guint32 dor_index)
3725 {
3726         guint32 table, idx;
3727
3728         table = dor_index & 0x03;
3729         idx = dor_index >> 2;
3730
3731         switch (table){
3732         case 0: /* TypeDef */
3733                 return MONO_TOKEN_TYPE_DEF | idx;
3734         case 1: /* TypeRef */
3735                 return MONO_TOKEN_TYPE_REF | idx;
3736         case 2: /* TypeSpec */
3737                 return MONO_TOKEN_TYPE_SPEC | idx;
3738         default:
3739                 g_assert_not_reached ();
3740         }
3741
3742         return 0;
3743 }
3744
3745 /*
3746  * We use this to pass context information to the row locator
3747  */
3748 typedef struct {
3749         int idx;                        /* The index that we are trying to locate */
3750         int col_idx;            /* The index in the row where idx may be stored */
3751         MonoTableInfo *t;       /* pointer to the table */
3752         guint32 result;
3753 } locator_t;
3754
3755 /*
3756  * How the row locator works.
3757  *
3758  *   Table A
3759  *   ___|___
3760  *   ___|___         Table B
3761  *   ___|___------>  _______
3762  *   ___|___         _______
3763  *   
3764  * A column in the rows of table A references an index in table B.
3765  * For example A may be the TYPEDEF table and B the METHODDEF table.
3766  * 
3767  * Given an index in table B we want to get the row in table A
3768  * where the column n references our index in B.
3769  *
3770  * In the locator_t structure:
3771  *      t is table A
3772  *      col_idx is the column number
3773  *      index is the index in table B
3774  *      result will be the index in table A
3775  *
3776  * Examples:
3777  * Table A              Table B         column (in table A)
3778  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
3779  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
3780  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
3781  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
3782  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
3783  *
3784  * Note that we still don't support encoded indexes.
3785  *
3786  */
3787 static int
3788 typedef_locator (const void *a, const void *b)
3789 {
3790         locator_t *loc = (locator_t *) a;
3791         const char *bb = (const char *) b;
3792         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
3793         guint32 col, col_next;
3794
3795         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
3796
3797         if (loc->idx < col)
3798                 return -1;
3799
3800         /*
3801          * Need to check that the next row is valid.
3802          */
3803         if (typedef_index + 1 < loc->t->rows) {
3804                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
3805                 if (loc->idx >= col_next)
3806                         return 1;
3807
3808                 if (col == col_next)
3809                         return 1; 
3810         }
3811
3812         loc->result = typedef_index;
3813         
3814         return 0;
3815 }
3816
3817 static int
3818 table_locator (const void *a, const void *b)
3819 {
3820         locator_t *loc = (locator_t *) a;
3821         const char *bb = (const char *) b;
3822         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
3823         guint32 col;
3824         
3825         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
3826
3827         if (loc->idx == col) {
3828                 loc->result = table_index;
3829                 return 0;
3830         }
3831         if (loc->idx < col)
3832                 return -1;
3833         else 
3834                 return 1;
3835 }
3836
3837 static int
3838 declsec_locator (const void *a, const void *b)
3839 {
3840         locator_t *loc = (locator_t *) a;
3841         const char *bb = (const char *) b;
3842         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
3843         guint32 col;
3844
3845         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
3846
3847         if (loc->idx == col) {
3848                 loc->result = table_index;
3849                 return 0;
3850         }
3851         if (loc->idx < col)
3852                 return -1;
3853         else
3854                 return 1;
3855 }
3856
3857 /**
3858  * search_ptr_table:
3859  *
3860  *  Return the 1-based row index in TABLE, which must be one of the *Ptr tables, 
3861  * which contains IDX.
3862  */
3863 static guint32
3864 search_ptr_table (MonoImage *image, int table, int idx)
3865 {
3866         MonoTableInfo *ptrdef = &image->tables [table];
3867         int i;
3868
3869         /* Use a linear search to find our index in the table */
3870         for (i = 0; i < ptrdef->rows; i ++)
3871                 /* All the Ptr tables have the same structure */
3872                 if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
3873                         break;
3874
3875         if (i < ptrdef->rows)
3876                 return i + 1;
3877         else
3878                 return idx;
3879 }
3880
3881 /**
3882  * mono_metadata_typedef_from_field:
3883  * @meta: metadata context
3884  * @index: FieldDef token
3885  *
3886  * Returns: the 1-based index into the TypeDef table of the type that
3887  * declared the field described by @index, or 0 if not found.
3888  */
3889 guint32
3890 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
3891 {
3892         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
3893         locator_t loc;
3894
3895         if (!tdef->base)
3896                 return 0;
3897
3898         loc.idx = mono_metadata_token_index (index);
3899         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
3900         loc.t = tdef;
3901
3902         if (meta->uncompressed_metadata)
3903                 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
3904
3905         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
3906                 return 0;
3907
3908         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3909         return loc.result + 1;
3910 }
3911
3912 /*
3913  * mono_metadata_typedef_from_method:
3914  * @meta: metadata context
3915  * @index: MethodDef token
3916  *
3917  * Returns: the 1-based index into the TypeDef table of the type that
3918  * declared the method described by @index.  0 if not found.
3919  */
3920 guint32
3921 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
3922 {
3923         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
3924         locator_t loc;
3925         
3926         if (!tdef->base)
3927                 return 0;
3928
3929         loc.idx = mono_metadata_token_index (index);
3930         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
3931         loc.t = tdef;
3932
3933         if (meta->uncompressed_metadata)
3934                 loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
3935
3936         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
3937                 return 0;
3938
3939         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3940         return loc.result + 1;
3941 }
3942
3943 /*
3944  * mono_metadata_interfaces_from_typedef_full:
3945  * @meta: metadata context
3946  * @index: typedef token
3947  * @interfaces: Out parameter used to store the interface array
3948  * @count: Out parameter used to store the number of interfaces
3949  * @heap_alloc_result: if TRUE the result array will be g_malloc'd
3950  * @context: The generic context
3951  * 
3952  * The array of interfaces that the @index typedef token implements is returned in
3953  * @interfaces. The number of elements in the array is returned in @count. 
3954  *
3955  * LOCKING: Assumes the loader lock is held.
3956  *
3957  * Returns: TRUE on success, FALSE on failure.
3958  */
3959 gboolean
3960 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context)
3961 {
3962         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
3963         locator_t loc;
3964         guint32 start, pos;
3965         guint32 cols [MONO_INTERFACEIMPL_SIZE];
3966         MonoClass **result;
3967
3968         *interfaces = NULL;
3969         *count = 0;
3970
3971         if (!tdef->base)
3972                 return TRUE;
3973
3974         loc.idx = mono_metadata_token_index (index);
3975         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
3976         loc.t = tdef;
3977
3978         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3979                 return TRUE;
3980
3981         start = loc.result;
3982         /*
3983          * We may end up in the middle of the rows... 
3984          */
3985         while (start > 0) {
3986                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
3987                         start--;
3988                 else
3989                         break;
3990         }
3991         pos = start;
3992         while (pos < tdef->rows) {
3993                 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
3994                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
3995                         break;
3996                 ++pos;
3997         }
3998
3999         if (heap_alloc_result)
4000                 result = g_new0 (MonoClass*, pos - start);
4001         else
4002                 result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
4003
4004         pos = start;
4005         while (pos < tdef->rows) {
4006                 MonoClass *iface;
4007                 
4008                 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4009                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4010                         break;
4011                 iface = mono_class_get_full (
4012                         meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
4013                 if (iface == NULL)
4014                         return FALSE;
4015                 result [pos - start] = iface;
4016                 ++pos;
4017         }
4018         *count = pos - start;
4019         *interfaces = result;
4020         return TRUE;
4021 }
4022
4023 /*
4024  * @meta: metadata context
4025  * @index: typedef token
4026  * @count: Out parameter used to store the number of interfaces
4027  * 
4028  * The array of interfaces that the @index typedef token implements is returned in
4029  * @interfaces. The number of elements in the array is returned in @count. The returned
4030  * array is g_malloc'd and the caller must free it.
4031  *
4032  * LOCKING: Acquires the loader lock .
4033  *
4034  * Returns: the interface array on success, NULL on failure.
4035  */
4036
4037 MonoClass**
4038 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
4039 {
4040         MonoClass **interfaces;
4041         gboolean rv;
4042
4043         mono_loader_lock ();
4044         rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL);
4045         mono_loader_unlock ();
4046         if (rv)
4047                 return interfaces;
4048         else
4049                 return NULL;
4050 }
4051
4052 /*
4053  * mono_metadata_nested_in_typedef:
4054  * @meta: metadata context
4055  * @index: typedef token
4056  * 
4057  * Returns: the 1-based index into the TypeDef table of the type
4058  * where the type described by @index is nested.
4059  * Retruns 0 if @index describes a non-nested type.
4060  */
4061 guint32
4062 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
4063 {
4064         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4065         locator_t loc;
4066         
4067         if (!tdef->base)
4068                 return 0;
4069
4070         loc.idx = mono_metadata_token_index (index);
4071         loc.col_idx = MONO_NESTED_CLASS_NESTED;
4072         loc.t = tdef;
4073
4074         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4075                 return 0;
4076
4077         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4078         return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
4079 }
4080
4081 /*
4082  * mono_metadata_nesting_typedef:
4083  * @meta: metadata context
4084  * @index: typedef token
4085  * 
4086  * Returns: the 1-based index into the TypeDef table of the first type
4087  * that is nested inside the type described by @index. The search starts at
4088  * @start_index.  returns 0 if no such type is found.
4089  */
4090 guint32
4091 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
4092 {
4093         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4094         guint32 start;
4095         guint32 class_index = mono_metadata_token_index (index);
4096         
4097         if (!tdef->base)
4098                 return 0;
4099
4100         start = start_index;
4101
4102         while (start <= tdef->rows) {
4103                 if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
4104                         break;
4105                 else
4106                         start++;
4107         }
4108
4109         if (start > tdef->rows)
4110                 return 0;
4111         else
4112                 return start;
4113 }
4114
4115 /*
4116  * mono_metadata_packing_from_typedef:
4117  * @meta: metadata context
4118  * @index: token representing a type
4119  * 
4120  * Returns: the info stored in the ClassLAyout table for the given typedef token
4121  * into the @packing and @size pointers.
4122  * Returns 0 if the info is not found.
4123  */
4124 guint32
4125 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
4126 {
4127         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
4128         locator_t loc;
4129         guint32 cols [MONO_CLASS_LAYOUT_SIZE];
4130         
4131         if (!tdef->base)
4132                 return 0;
4133
4134         loc.idx = mono_metadata_token_index (index);
4135         loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
4136         loc.t = tdef;
4137
4138         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4139                 return 0;
4140
4141         mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
4142         if (packing)
4143                 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
4144         if (size)
4145                 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
4146
4147         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4148         return loc.result + 1;
4149 }
4150
4151 /*
4152  * mono_metadata_custom_attrs_from_index:
4153  * @meta: metadata context
4154  * @index: token representing the parent
4155  * 
4156  * Returns: the 1-based index into the CustomAttribute table of the first 
4157  * attribute which belongs to the metadata object described by @index.
4158  * Returns 0 if no such attribute is found.
4159  */
4160 guint32
4161 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
4162 {
4163         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4164         locator_t loc;
4165         
4166         if (!tdef->base)
4167                 return 0;
4168
4169         loc.idx = index;
4170         loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
4171         loc.t = tdef;
4172
4173         /* FIXME: Index translation */
4174
4175         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4176                 return 0;
4177
4178         /* Find the first entry by searching backwards */
4179         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
4180                 loc.result --;
4181
4182         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4183         return loc.result + 1;
4184 }
4185
4186 /*
4187  * mono_metadata_declsec_from_index:
4188  * @meta: metadata context
4189  * @index: token representing the parent
4190  * 
4191  * Returns: the 0-based index into the DeclarativeSecurity table of the first 
4192  * attribute which belongs to the metadata object described by @index.
4193  * Returns -1 if no such attribute is found.
4194  */
4195 guint32
4196 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
4197 {
4198         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
4199         locator_t loc;
4200
4201         if (!tdef->base)
4202                 return -1;
4203
4204         loc.idx = index;
4205         loc.col_idx = MONO_DECL_SECURITY_PARENT;
4206         loc.t = tdef;
4207
4208         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
4209                 return -1;
4210
4211         /* Find the first entry by searching backwards */
4212         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
4213                 loc.result --;
4214
4215         return loc.result;
4216 }
4217
4218 #ifdef DEBUG
4219 static void
4220 mono_backtrace (int limit)
4221 {
4222         void *array[limit];
4223         char **names;
4224         int i;
4225         backtrace (array, limit);
4226         names = backtrace_symbols (array, limit);
4227         for (i =0; i < limit; ++i) {
4228                 g_print ("\t%s\n", names [i]);
4229         }
4230         g_free (names);
4231 }
4232 #endif
4233
4234 #ifndef __GNUC__
4235 /*#define __alignof__(a) sizeof(a)*/
4236 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4237 #endif
4238
4239 /*
4240  * mono_type_size:
4241  * @t: the type to return the size of
4242  *
4243  * Returns: the number of bytes required to hold an instance of this
4244  * type in memory
4245  */
4246 int
4247 mono_type_size (MonoType *t, int *align)
4248 {
4249         if (!t) {
4250                 *align = 1;
4251                 return 0;
4252         }
4253         if (t->byref) {
4254                 *align = __alignof__(gpointer);
4255                 return sizeof (gpointer);
4256         }
4257
4258         switch (t->type){
4259         case MONO_TYPE_VOID:
4260                 *align = 1;
4261                 return 0;
4262         case MONO_TYPE_BOOLEAN:
4263                 *align = __alignof__(gint8);
4264                 return 1;
4265         case MONO_TYPE_I1:
4266         case MONO_TYPE_U1:
4267                 *align = __alignof__(gint8);
4268                 return 1;
4269         case MONO_TYPE_CHAR:
4270         case MONO_TYPE_I2:
4271         case MONO_TYPE_U2:
4272                 *align = __alignof__(gint16);
4273                 return 2;               
4274         case MONO_TYPE_I4:
4275         case MONO_TYPE_U4:
4276                 *align = __alignof__(gint32);
4277                 return 4;
4278         case MONO_TYPE_R4:
4279                 *align = __alignof__(float);
4280                 return 4;
4281         case MONO_TYPE_I8:
4282         case MONO_TYPE_U8:
4283                 *align = __alignof__(gint64);
4284                 return 8;               
4285         case MONO_TYPE_R8:
4286                 *align = __alignof__(double);
4287                 return 8;               
4288         case MONO_TYPE_I:
4289         case MONO_TYPE_U:
4290                 *align = __alignof__(gpointer);
4291                 return sizeof (gpointer);
4292         case MONO_TYPE_STRING:
4293                 *align = __alignof__(gpointer);
4294                 return sizeof (gpointer);
4295         case MONO_TYPE_OBJECT:
4296                 *align = __alignof__(gpointer);
4297                 return sizeof (gpointer);
4298         case MONO_TYPE_VALUETYPE: {
4299                 if (t->data.klass->enumtype)
4300                         return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
4301                 else
4302                         return mono_class_value_size (t->data.klass, (guint32*)align);
4303         }
4304         case MONO_TYPE_CLASS:
4305         case MONO_TYPE_SZARRAY:
4306         case MONO_TYPE_PTR:
4307         case MONO_TYPE_FNPTR:
4308         case MONO_TYPE_ARRAY:
4309                 *align = __alignof__(gpointer);
4310                 return sizeof (gpointer);
4311         case MONO_TYPE_TYPEDBYREF:
4312                 return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
4313         case MONO_TYPE_GENERICINST: {
4314                 MonoGenericClass *gclass = t->data.generic_class;
4315                 MonoClass *container_class = gclass->container_class;
4316
4317                 // g_assert (!gclass->inst->is_open);
4318
4319                 if (container_class->valuetype) {
4320                         if (container_class->enumtype)
4321                                 return mono_type_size (mono_class_enum_basetype (container_class), align);
4322                         else
4323                                 return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
4324                 } else {
4325                         *align = __alignof__(gpointer);
4326                         return sizeof (gpointer);
4327                 }
4328         }
4329         case MONO_TYPE_VAR:
4330         case MONO_TYPE_MVAR:
4331                 /* FIXME: Martin, this is wrong. */
4332                 *align = __alignof__(gpointer);
4333                 return sizeof (gpointer);
4334         default:
4335                 g_error ("mono_type_size: type 0x%02x unknown", t->type);
4336         }
4337         return 0;
4338 }
4339
4340 /*
4341  * mono_type_stack_size:
4342  * @t: the type to return the size it uses on the stack
4343  *
4344  * Returns: the number of bytes required to hold an instance of this
4345  * type on the runtime stack
4346  */
4347 int
4348 mono_type_stack_size (MonoType *t, int *align)
4349 {
4350         return mono_type_stack_size_internal (t, align, FALSE);
4351 }
4352
4353 int
4354 mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
4355 {
4356         int tmp;
4357 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4358         int stack_slot_size = sizeof (gpointer);
4359         int stack_slot_align = __alignof__ (gpointer);
4360 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4361         int stack_slot_size = SIZEOF_REGISTER;
4362         int stack_slot_align = SIZEOF_REGISTER;
4363 #endif
4364
4365         g_assert (t != NULL);
4366
4367         if (!align)
4368                 align = &tmp;
4369
4370         if (t->byref) {
4371                 *align = stack_slot_align;
4372                 return stack_slot_size;
4373         }
4374
4375         switch (t->type){
4376         case MONO_TYPE_BOOLEAN:
4377         case MONO_TYPE_CHAR:
4378         case MONO_TYPE_I1:
4379         case MONO_TYPE_U1:
4380         case MONO_TYPE_I2:
4381         case MONO_TYPE_U2:
4382         case MONO_TYPE_I4:
4383         case MONO_TYPE_U4:
4384         case MONO_TYPE_I:
4385         case MONO_TYPE_U:
4386         case MONO_TYPE_STRING:
4387         case MONO_TYPE_OBJECT:
4388         case MONO_TYPE_CLASS:
4389         case MONO_TYPE_SZARRAY:
4390         case MONO_TYPE_PTR:
4391         case MONO_TYPE_FNPTR:
4392         case MONO_TYPE_ARRAY:
4393                 *align = stack_slot_align;
4394                 return stack_slot_size;
4395         case MONO_TYPE_VAR:
4396         case MONO_TYPE_MVAR:
4397                 g_assert (allow_open);
4398                 *align = stack_slot_align;
4399                 return stack_slot_size;
4400         case MONO_TYPE_TYPEDBYREF:
4401                 *align = stack_slot_align;
4402                 return stack_slot_size * 3;
4403         case MONO_TYPE_R4:
4404                 *align = __alignof__(float);
4405                 return sizeof (float);          
4406         case MONO_TYPE_I8:
4407         case MONO_TYPE_U8:
4408                 *align = __alignof__(gint64);
4409                 return sizeof (gint64);         
4410         case MONO_TYPE_R8:
4411                 *align = __alignof__(double);
4412                 return sizeof (double);
4413         case MONO_TYPE_VALUETYPE: {
4414                 guint32 size;
4415
4416                 if (t->data.klass->enumtype)
4417                         return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
4418                 else {
4419                         size = mono_class_value_size (t->data.klass, (guint32*)align);
4420
4421                         *align = *align + stack_slot_align - 1;
4422                         *align &= ~(stack_slot_align - 1);
4423
4424                         size += stack_slot_size - 1;
4425                         size &= ~(stack_slot_size - 1);
4426
4427                         return size;
4428                 }
4429         }
4430         case MONO_TYPE_GENERICINST: {
4431                 MonoGenericClass *gclass = t->data.generic_class;
4432                 MonoClass *container_class = gclass->container_class;
4433
4434                 if (!allow_open)
4435                         g_assert (!gclass->context.class_inst->is_open);
4436
4437                 if (container_class->valuetype) {
4438                         if (container_class->enumtype)
4439                                 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
4440                         else {
4441                                 guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
4442
4443                                 *align = *align + stack_slot_align - 1;
4444                                 *align &= ~(stack_slot_align - 1);
4445
4446                                 size += stack_slot_size - 1;
4447                                 size &= ~(stack_slot_size - 1);
4448
4449                                 return size;
4450                         }
4451                 } else {
4452                         *align = stack_slot_align;
4453                         return stack_slot_size;
4454                 }
4455         }
4456         default:
4457                 g_error ("type 0x%02x unknown", t->type);
4458         }
4459         return 0;
4460 }
4461
4462 gboolean
4463 mono_type_generic_inst_is_valuetype (MonoType *type)
4464 {
4465         g_assert (type->type == MONO_TYPE_GENERICINST);
4466         return type->data.generic_class->container_class->valuetype;
4467 }
4468
4469 gboolean
4470 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
4471 {
4472         return gclass->container_class->valuetype;
4473 }
4474
4475 static gboolean
4476 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
4477 {
4478         MonoGenericInst *i1 = g1->context.class_inst;
4479         MonoGenericInst *i2 = g2->context.class_inst;
4480
4481         if (g1->is_dynamic != g2->is_dynamic)
4482                 return FALSE;
4483         if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
4484                 return FALSE;
4485         if (!mono_generic_inst_equal_full (i1, i2, signature_only))
4486                 return FALSE;
4487         return g1->is_tb_open == g2->is_tb_open;
4488 }
4489
4490 static gboolean
4491 _mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
4492 {
4493         MonoGenericInst *i1 = g1->context.class_inst;
4494         MonoGenericInst *i2 = c2->generic_container->context.class_inst;
4495
4496         if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
4497                 return FALSE;
4498         if (!mono_generic_inst_equal_full (i1, i2, signature_only))
4499                 return FALSE;
4500         return !g1->is_tb_open;
4501 }
4502
4503 guint
4504 mono_metadata_generic_context_hash (const MonoGenericContext *context)
4505 {
4506         /* FIXME: check if this seed is good enough */
4507         guint hash = 0xc01dfee7;
4508         if (context->class_inst)
4509                 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
4510         if (context->method_inst)
4511                 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
4512         return hash;
4513 }
4514
4515 gboolean
4516 mono_metadata_generic_context_equal (const MonoGenericContext *g1, const MonoGenericContext *g2)
4517 {
4518         return g1->class_inst == g2->class_inst && g1->method_inst == g2->method_inst;
4519 }
4520
4521 /*
4522  * mono_metadata_str_hash:
4523  *
4524  *   This should be used instead of g_str_hash for computing hash codes visible
4525  * outside this module, since g_str_hash () is not guaranteed to be stable
4526  * (its not the same in eglib for example).
4527  */
4528 guint
4529 mono_metadata_str_hash (gconstpointer v1)
4530 {
4531         /* Same as g_str_hash () in glib */
4532         char *p = (char *) v1;
4533         guint hash = *p;
4534
4535         while (*p++) {
4536                 if (*p)
4537                         hash = (hash << 5) - hash + *p;
4538         }
4539
4540         return hash;
4541
4542
4543 /*
4544  * mono_metadata_type_hash:
4545  * @t1: a type
4546  *
4547  * Computes an hash value for @t1 to be used in GHashTable.
4548  * The returned hash is guaranteed to be the same across executions.
4549  */
4550 guint
4551 mono_metadata_type_hash (MonoType *t1)
4552 {
4553         guint hash = t1->type;
4554
4555         hash |= t1->byref << 6; /* do not collide with t1->type values */
4556         switch (t1->type) {
4557         case MONO_TYPE_VALUETYPE:
4558         case MONO_TYPE_CLASS:
4559         case MONO_TYPE_SZARRAY: {
4560                 MonoClass *class = t1->data.klass;
4561                 /*
4562                  * Dynamic classes must not be hashed on their type since it can change
4563                  * during runtime. For example, if we hash a reference type that is
4564                  * later made into a valuetype.
4565                  *
4566                  * This is specially problematic with generic instances since they are
4567                  * inserted in a bunch of hash tables before been finished.
4568                  */
4569                 if (class->image->dynamic)
4570                         return (t1->byref << 6) | mono_metadata_str_hash (class->name);
4571                 return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name);
4572         }
4573         case MONO_TYPE_PTR:
4574                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
4575         case MONO_TYPE_ARRAY:
4576                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
4577         case MONO_TYPE_GENERICINST:
4578                 return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
4579         }
4580         return hash;
4581 }
4582
4583 static gboolean
4584 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
4585 {
4586         if (p1 == p2)
4587                 return TRUE;
4588         if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
4589                 return FALSE;
4590
4591         /*
4592          * We have to compare the image as well because if we didn't,
4593          * the generic_inst_cache lookup wouldn't care about the image
4594          * of generic params, so what could happen is that a generic
4595          * inst with params from image A is put into the cache, then
4596          * image B gets that generic inst from the cache, image A is
4597          * unloaded, so the inst is deleted, but image B still retains
4598          * a pointer to it.
4599          *
4600          * The AOT runtime doesn't set the image when it's decoding
4601          * types, so we only compare it when the owner is NULL.
4602          */
4603         if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2) &&
4604             (mono_generic_param_owner (p1) || p1->image == p2->image))
4605                 return TRUE;
4606
4607         /*
4608          * If `signature_only' is true, we're comparing two (method) signatures.
4609          * In this case, the owner of two type parameters doesn't need to match.
4610          */
4611
4612         return signature_only;
4613 }
4614
4615 static gboolean
4616 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
4617 {
4618         if (c1 == c2)
4619                 return TRUE;
4620         if (c1->generic_class && c2->generic_class)
4621                 return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
4622         if (c1->generic_class && c2->generic_container)
4623                 return _mono_metadata_generic_class_container_equal (c1->generic_class, c2, signature_only);
4624         if (c1->generic_container && c2->generic_class)
4625                 return _mono_metadata_generic_class_container_equal (c2->generic_class, c1, signature_only);
4626         if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
4627                 return mono_metadata_generic_param_equal (
4628                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
4629         if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
4630                 return mono_metadata_generic_param_equal (
4631                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
4632         if (signature_only &&
4633             (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
4634                 return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
4635         return FALSE;
4636 }
4637
4638 static gboolean
4639 mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
4640 {
4641         gpointer iter1 = 0, iter2 = 0;
4642
4643         if (s1 == s2)
4644                 return TRUE;
4645         if (s1->call_convention != s2->call_convention)
4646                 return FALSE;
4647         if (s1->sentinelpos != s2->sentinelpos)
4648                 return FALSE;
4649         if (s1->hasthis != s2->hasthis)
4650                 return FALSE;
4651         if (s1->explicit_this != s2->explicit_this)
4652                 return FALSE;
4653         if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
4654                 return FALSE;
4655         if (s1->param_count != s2->param_count)
4656                 return FALSE;
4657
4658         while (TRUE) {
4659                 MonoType *t1 = mono_signature_get_params (s1, &iter1);
4660                 MonoType *t2 = mono_signature_get_params (s2, &iter2);
4661
4662                 if (t1 == NULL || t2 == NULL)
4663                         return (t1 == t2);
4664                 if (! do_mono_metadata_type_equal (t1, t2, signature_only))
4665                         return FALSE;
4666         }
4667 }
4668
4669 /*
4670  * mono_metadata_type_equal:
4671  * @t1: a type
4672  * @t2: another type
4673  *
4674  * Determine if @t1 and @t2 represent the same type.
4675  * Returns: #TRUE if @t1 and @t2 are equal.
4676  */
4677 static gboolean
4678 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
4679 {
4680         if (t1->type != t2->type || t1->byref != t2->byref)
4681                 return FALSE;
4682
4683         switch (t1->type) {
4684         case MONO_TYPE_VOID:
4685         case MONO_TYPE_BOOLEAN:
4686         case MONO_TYPE_CHAR:
4687         case MONO_TYPE_I1:
4688         case MONO_TYPE_U1:
4689         case MONO_TYPE_I2:
4690         case MONO_TYPE_U2:
4691         case MONO_TYPE_I4:
4692         case MONO_TYPE_U4:
4693         case MONO_TYPE_I8:
4694         case MONO_TYPE_U8:
4695         case MONO_TYPE_R4:
4696         case MONO_TYPE_R8:
4697         case MONO_TYPE_STRING:
4698         case MONO_TYPE_I:
4699         case MONO_TYPE_U:
4700         case MONO_TYPE_OBJECT:
4701         case MONO_TYPE_TYPEDBYREF:
4702                 return TRUE;
4703         case MONO_TYPE_VALUETYPE:
4704         case MONO_TYPE_CLASS:
4705         case MONO_TYPE_SZARRAY:
4706                 return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
4707         case MONO_TYPE_PTR:
4708                 return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
4709         case MONO_TYPE_ARRAY:
4710                 if (t1->data.array->rank != t2->data.array->rank)
4711                         return FALSE;
4712                 return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
4713         case MONO_TYPE_GENERICINST:
4714                 return _mono_metadata_generic_class_equal (
4715                         t1->data.generic_class, t2->data.generic_class, signature_only);
4716         case MONO_TYPE_VAR:
4717                 return mono_metadata_generic_param_equal (
4718                         t1->data.generic_param, t2->data.generic_param, signature_only);
4719         case MONO_TYPE_MVAR:
4720                 return mono_metadata_generic_param_equal (
4721                         t1->data.generic_param, t2->data.generic_param, signature_only);
4722         case MONO_TYPE_FNPTR:
4723                 return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
4724         default:
4725                 g_error ("implement type compare for %0x!", t1->type);
4726                 return FALSE;
4727         }
4728
4729         return FALSE;
4730 }
4731
4732 gboolean
4733 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
4734 {
4735         return do_mono_metadata_type_equal (t1, t2, FALSE);
4736 }
4737
4738 /**
4739  * mono_metadata_type_equal_full:
4740  * @t1: a type
4741  * @t2: another type
4742  * @signature_only: if signature only comparison should be made
4743  *
4744  * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
4745  * behaves the same way as mono_metadata_type_equal.
4746  * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
4747  * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
4748  */
4749 gboolean
4750 mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
4751 {
4752         return do_mono_metadata_type_equal (t1, t2, signature_only);
4753 }
4754
4755 /**
4756  * mono_metadata_signature_equal:
4757  * @sig1: a signature
4758  * @sig2: another signature
4759  *
4760  * Determine if @sig1 and @sig2 represent the same signature, with the
4761  * same number of arguments and the same types.
4762  * Returns: #TRUE if @sig1 and @sig2 are equal.
4763  */
4764 gboolean
4765 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
4766 {
4767         int i;
4768
4769         if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
4770                 return FALSE;
4771
4772         if (sig1->generic_param_count != sig2->generic_param_count)
4773                 return FALSE;
4774
4775         /*
4776          * We're just comparing the signatures of two methods here:
4777          *
4778          * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
4779          * U and V are equal here.
4780          *
4781          * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
4782          */
4783
4784         for (i = 0; i < sig1->param_count; i++) { 
4785                 MonoType *p1 = sig1->params[i];
4786                 MonoType *p2 = sig2->params[i];
4787                 
4788                 /* if (p1->attrs != p2->attrs)
4789                         return FALSE;
4790                 */
4791                 if (!do_mono_metadata_type_equal (p1, p2, TRUE))
4792                         return FALSE;
4793         }
4794
4795         if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
4796                 return FALSE;
4797         return TRUE;
4798 }
4799
4800 /**
4801  * mono_metadata_type_dup:
4802  * @image: image to alloc memory from
4803  * @original: type to duplicate
4804  *
4805  * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
4806  */
4807 MonoType *
4808 mono_metadata_type_dup (MonoImage *image, const MonoType *o)
4809 {
4810         MonoType *r = NULL;
4811         int sizeof_o = MONO_SIZEOF_TYPE;
4812         if (o->num_mods)
4813                 sizeof_o += o->num_mods  * sizeof (MonoCustomMod);
4814
4815         r = image ? mono_image_alloc0 (image, sizeof_o) : g_malloc (sizeof_o);
4816
4817         memcpy (r, o, sizeof_o);
4818
4819         if (o->type == MONO_TYPE_PTR) {
4820                 r->data.type = mono_metadata_type_dup (image, o->data.type);
4821         } else if (o->type == MONO_TYPE_ARRAY) {
4822                 r->data.array = mono_dup_array_type (image, o->data.array);
4823         } else if (o->type == MONO_TYPE_FNPTR) {
4824                 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
4825                 r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
4826         }
4827         return r;
4828 }
4829
4830 guint
4831 mono_signature_hash (MonoMethodSignature *sig)
4832 {
4833         guint i, res = sig->ret->type;
4834
4835         for (i = 0; i < sig->param_count; i++)
4836                 res = (res << 5) - res + mono_type_hash (sig->params[i]);
4837
4838         return res;
4839 }
4840
4841 /*
4842  * mono_metadata_encode_value:
4843  * @value: value to encode
4844  * @buf: buffer where to write the compressed representation
4845  * @endbuf: pointer updated to point at the end of the encoded output
4846  *
4847  * Encodes the value @value in the compressed representation used
4848  * in metadata and stores the result in @buf. @buf needs to be big
4849  * enough to hold the data (4 bytes).
4850  */
4851 void
4852 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
4853 {
4854         char *p = buf;
4855         
4856         if (value < 0x80)
4857                 *p++ = value;
4858         else if (value < 0x4000) {
4859                 p [0] = 0x80 | (value >> 8);
4860                 p [1] = value & 0xff;
4861                 p += 2;
4862         } else {
4863                 p [0] = (value >> 24) | 0xc0;
4864                 p [1] = (value >> 16) & 0xff;
4865                 p [2] = (value >> 8) & 0xff;
4866                 p [3] = value & 0xff;
4867                 p += 4;
4868         }
4869         if (endbuf)
4870                 *endbuf = p;
4871 }
4872
4873 /*
4874  * mono_metadata_field_info:
4875  * @meta: the Image the field is defined in
4876  * @index: the index in the field table representing the field
4877  * @offset: a pointer to an integer where to store the offset that 
4878  * may have been specified for the field in a FieldLayout table
4879  * @rva: a pointer to the RVA of the field data in the image that
4880  * may have been defined in a FieldRVA table
4881  * @marshal_spec: a pointer to the marshal spec that may have been 
4882  * defined for the field in a FieldMarshal table.
4883  *
4884  * Gather info for field @index that may have been defined in the FieldLayout, 
4885  * FieldRVA and FieldMarshal tables.
4886  * Either of offset, rva and marshal_spec can be NULL if you're not interested 
4887  * in the data.
4888  */
4889 void
4890 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
4891                           MonoMarshalSpec **marshal_spec)
4892 {
4893         mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
4894 }
4895
4896 void
4897 mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
4898                           MonoMarshalSpec **marshal_spec)
4899 {
4900         mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
4901 }
4902
4903 static void
4904 mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
4905                                        MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
4906 {
4907         MonoTableInfo *tdef;
4908         locator_t loc;
4909
4910         loc.idx = index + 1;
4911         if (meta->uncompressed_metadata)
4912                 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
4913
4914         if (offset) {
4915                 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
4916
4917                 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
4918                 loc.t = tdef;
4919
4920                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
4921                         *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
4922                 } else {
4923                         *offset = (guint32)-1;
4924                 }
4925         }
4926         if (rva) {
4927                 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
4928
4929                 loc.col_idx = MONO_FIELD_RVA_FIELD;
4930                 loc.t = tdef;
4931                 
4932                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
4933                         /*
4934                          * LAMESPEC: There is no signature, no nothing, just the raw data.
4935                          */
4936                         *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
4937                 } else {
4938                         *rva = 0;
4939                 }
4940         }
4941         if (marshal_spec) {
4942                 const char *p;
4943                 
4944                 if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
4945                         *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, p);
4946                 }
4947         }
4948
4949 }
4950
4951 /*
4952  * mono_metadata_get_constant_index:
4953  * @meta: the Image the field is defined in
4954  * @index: the token that may have a row defined in the constants table
4955  * @hint: possible position for the row
4956  *
4957  * @token must be a FieldDef, ParamDef or PropertyDef token.
4958  *
4959  * Returns: the index into the Constants table or 0 if not found.
4960  */
4961 guint32
4962 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
4963 {
4964         MonoTableInfo *tdef;
4965         locator_t loc;
4966         guint32 index = mono_metadata_token_index (token);
4967
4968         tdef = &meta->tables [MONO_TABLE_CONSTANT];
4969         index <<= MONO_HASCONSTANT_BITS;
4970         switch (mono_metadata_token_table (token)) {
4971         case MONO_TABLE_FIELD:
4972                 index |= MONO_HASCONSTANT_FIEDDEF;
4973                 break;
4974         case MONO_TABLE_PARAM:
4975                 index |= MONO_HASCONSTANT_PARAM;
4976                 break;
4977         case MONO_TABLE_PROPERTY:
4978                 index |= MONO_HASCONSTANT_PROPERTY;
4979                 break;
4980         default:
4981                 g_warning ("Not a valid token for the constant table: 0x%08x", token);
4982                 return 0;
4983         }
4984         loc.idx = index;
4985         loc.col_idx = MONO_CONSTANT_PARENT;
4986         loc.t = tdef;
4987
4988         /* FIXME: Index translation */
4989
4990         if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
4991                 return hint;
4992
4993         if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
4994                 return loc.result + 1;
4995         }
4996         return 0;
4997 }
4998
4999 /*
5000  * mono_metadata_events_from_typedef:
5001  * @meta: metadata context
5002  * @index: 0-based index (in the TypeDef table) describing a type
5003  *
5004  * Returns: the 0-based index in the Event table for the events in the
5005  * type. The last event that belongs to the type (plus 1) is stored
5006  * in the @end_idx pointer.
5007  */
5008 guint32
5009 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5010 {
5011         locator_t loc;
5012         guint32 start, end;
5013         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_EVENTMAP];
5014
5015         *end_idx = 0;
5016         
5017         if (!tdef->base)
5018                 return 0;
5019
5020         loc.t = tdef;
5021         loc.col_idx = MONO_EVENT_MAP_PARENT;
5022         loc.idx = index + 1;
5023
5024         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5025                 return 0;
5026         
5027         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
5028         if (loc.result + 1 < tdef->rows) {
5029                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
5030         } else {
5031                 end = meta->tables [MONO_TABLE_EVENT].rows;
5032         }
5033
5034         *end_idx = end;
5035         return start - 1;
5036 }
5037
5038 /*
5039  * mono_metadata_methods_from_event:
5040  * @meta: metadata context
5041  * @index: 0-based index (in the Event table) describing a event
5042  *
5043  * Returns: the 0-based index in the MethodDef table for the methods in the
5044  * event. The last method that belongs to the event (plus 1) is stored
5045  * in the @end_idx pointer.
5046  */
5047 guint32
5048 mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_idx)
5049 {
5050         locator_t loc;
5051         guint start, end;
5052         guint32 cols [MONO_METHOD_SEMA_SIZE];
5053         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5054
5055         *end_idx = 0;
5056         if (!msemt->base)
5057                 return 0;
5058
5059         if (meta->uncompressed_metadata)
5060             index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
5061
5062         loc.t = msemt;
5063         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5064         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
5065
5066         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5067                 return 0;
5068
5069         start = loc.result;
5070         /*
5071          * We may end up in the middle of the rows... 
5072          */
5073         while (start > 0) {
5074                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5075                         start--;
5076                 else
5077                         break;
5078         }
5079         end = start + 1;
5080         while (end < msemt->rows) {
5081                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5082                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5083                         break;
5084                 ++end;
5085         }
5086         *end_idx = end;
5087         return start;
5088 }
5089
5090 /*
5091  * mono_metadata_properties_from_typedef:
5092  * @meta: metadata context
5093  * @index: 0-based index (in the TypeDef table) describing a type
5094  *
5095  * Returns: the 0-based index in the Property table for the properties in the
5096  * type. The last property that belongs to the type (plus 1) is stored
5097  * in the @end_idx pointer.
5098  */
5099 guint32
5100 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5101 {
5102         locator_t loc;
5103         guint32 start, end;
5104         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_PROPERTYMAP];
5105
5106         *end_idx = 0;
5107         
5108         if (!tdef->base)
5109                 return 0;
5110
5111         loc.t = tdef;
5112         loc.col_idx = MONO_PROPERTY_MAP_PARENT;
5113         loc.idx = index + 1;
5114
5115         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5116                 return 0;
5117         
5118         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
5119         if (loc.result + 1 < tdef->rows) {
5120                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
5121         } else {
5122                 end = meta->tables [MONO_TABLE_PROPERTY].rows;
5123         }
5124
5125         *end_idx = end;
5126         return start - 1;
5127 }
5128
5129 /*
5130  * mono_metadata_methods_from_property:
5131  * @meta: metadata context
5132  * @index: 0-based index (in the PropertyDef table) describing a property
5133  *
5134  * Returns: the 0-based index in the MethodDef table for the methods in the
5135  * property. The last method that belongs to the property (plus 1) is stored
5136  * in the @end_idx pointer.
5137  */
5138 guint32
5139 mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *end_idx)
5140 {
5141         locator_t loc;
5142         guint start, end;
5143         guint32 cols [MONO_METHOD_SEMA_SIZE];
5144         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5145
5146         *end_idx = 0;
5147         if (!msemt->base)
5148                 return 0;
5149
5150         if (meta->uncompressed_metadata)
5151             index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
5152
5153         loc.t = msemt;
5154         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5155         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
5156
5157         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5158                 return 0;
5159
5160         start = loc.result;
5161         /*
5162          * We may end up in the middle of the rows... 
5163          */
5164         while (start > 0) {
5165                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5166                         start--;
5167                 else
5168                         break;
5169         }
5170         end = start + 1;
5171         while (end < msemt->rows) {
5172                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5173                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5174                         break;
5175                 ++end;
5176         }
5177         *end_idx = end;
5178         return start;
5179 }
5180
5181 guint32
5182 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
5183 {
5184         locator_t loc;
5185         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_IMPLMAP];
5186
5187         if (!tdef->base)
5188                 return 0;
5189
5190         /* No index translation seems to be needed */
5191
5192         loc.t = tdef;
5193         loc.col_idx = MONO_IMPLMAP_MEMBER;
5194         loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
5195
5196         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5197                 return 0;
5198
5199         return loc.result + 1;
5200 }
5201
5202 /**
5203  * @image: context where the image is created
5204  * @type_spec:  typespec token
5205  *
5206  * Creates a MonoType representing the TypeSpec indexed by the @type_spec
5207  * token.
5208  */
5209 MonoType *
5210 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
5211 {
5212         guint32 idx = mono_metadata_token_index (type_spec);
5213         MonoTableInfo *t;
5214         guint32 cols [MONO_TYPESPEC_SIZE];
5215         const char *ptr;
5216         guint32 len;
5217         MonoType *type, *type2;
5218         MonoType stack_type;
5219
5220         mono_loader_lock ();
5221
5222         type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5223         if (type) {
5224                 mono_loader_unlock ();
5225                 return type;
5226         }
5227
5228         t = &image->tables [MONO_TABLE_TYPESPEC];
5229
5230         mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
5231         ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
5232
5233         if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
5234                 mono_loader_unlock ();
5235                 return NULL;
5236         }
5237
5238         len = mono_metadata_decode_value (ptr, &ptr);
5239
5240         type = &stack_type;
5241         memset (type, 0, MONO_SIZEOF_TYPE);
5242
5243         if (*ptr == MONO_TYPE_BYREF) {
5244                 type->byref = 1;
5245                 ptr++;
5246         }
5247
5248         if (!do_mono_metadata_parse_type (type, image, NULL, FALSE, ptr, &ptr)) {
5249                 mono_loader_unlock ();
5250                 return NULL;
5251         }
5252
5253         type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5254
5255         if (type2) {
5256                 mono_loader_unlock ();
5257                 return type2;
5258         }
5259
5260         type2 = mono_image_alloc (image, MONO_SIZEOF_TYPE);
5261         memcpy (type2, type, MONO_SIZEOF_TYPE);
5262         g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
5263
5264         mono_loader_unlock ();
5265
5266         return type2;
5267 }
5268
5269
5270 static char*
5271 mono_image_strndup (MonoImage *image, const char *data, guint len)
5272 {
5273         char *res;
5274         if (!image)
5275                 return g_strndup (data, len);
5276         res = mono_image_alloc (image, len + 1);
5277         memcpy (res, data, len);
5278         res [len] = 0;
5279         return res;
5280 }
5281
5282 MonoMarshalSpec *
5283 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
5284 {
5285         return mono_metadata_parse_marshal_spec_full (NULL, ptr);
5286 }
5287
5288 MonoMarshalSpec *
5289 mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
5290 {
5291         MonoMarshalSpec *res;
5292         int len;
5293         const char *start = ptr;
5294
5295         /* fixme: this is incomplete, but I cant find more infos in the specs */
5296
5297         if (image)
5298                 res = mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
5299         else
5300                 res = g_new0 (MonoMarshalSpec, 1);
5301         
5302         len = mono_metadata_decode_value (ptr, &ptr);
5303         res->native = *ptr++;
5304
5305         if (res->native == MONO_NATIVE_LPARRAY) {
5306                 res->data.array_data.param_num = -1;
5307                 res->data.array_data.num_elem = -1;
5308                 res->data.array_data.elem_mult = -1;
5309
5310                 if (ptr - start <= len)
5311                         res->data.array_data.elem_type = *ptr++;
5312                 if (ptr - start <= len)
5313                         res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
5314                 if (ptr - start <= len)
5315                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5316                 if (ptr - start <= len) {
5317                         /*
5318                          * LAMESPEC: Older spec versions say this parameter comes before 
5319                          * num_elem. Never spec versions don't talk about elem_mult at
5320                          * all, but csc still emits it, and it is used to distinguish
5321                          * between param_num being 0, and param_num being omitted.
5322                          * So if (param_num == 0) && (num_elem > 0), then
5323                          * elem_mult == 0 -> the array size is num_elem
5324                          * elem_mult == 1 -> the array size is @param_num + num_elem
5325                          */
5326                         res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
5327                 }
5328         } 
5329
5330         if (res->native == MONO_NATIVE_BYVALTSTR) {
5331                 if (ptr - start <= len)
5332                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5333         }
5334
5335         if (res->native == MONO_NATIVE_BYVALARRAY) {
5336                 if (ptr - start <= len)
5337                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5338         }
5339         
5340         if (res->native == MONO_NATIVE_CUSTOM) {
5341                 /* skip unused type guid */
5342                 len = mono_metadata_decode_value (ptr, &ptr);
5343                 ptr += len;
5344                 /* skip unused native type name */
5345                 len = mono_metadata_decode_value (ptr, &ptr);
5346                 ptr += len;
5347                 /* read custom marshaler type name */
5348                 len = mono_metadata_decode_value (ptr, &ptr);
5349                 res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);               
5350                 ptr += len;
5351                 /* read cookie string */
5352                 len = mono_metadata_decode_value (ptr, &ptr);
5353                 res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
5354         }
5355
5356         if (res->native == MONO_NATIVE_SAFEARRAY) {
5357                 res->data.safearray_data.elem_type = 0;
5358                 res->data.safearray_data.num_elem = 0;
5359                 if (ptr - start <= len)
5360                         res->data.safearray_data.elem_type = *ptr++;
5361                 if (ptr - start <= len)
5362                         res->data.safearray_data.num_elem = *ptr++;
5363         }
5364         return res;
5365 }
5366
5367 void 
5368 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
5369 {
5370         if (spec->native == MONO_NATIVE_CUSTOM) {
5371                 g_free (spec->data.custom_data.custom_name);
5372                 g_free (spec->data.custom_data.cookie);
5373         }
5374         g_free (spec);
5375 }
5376
5377 /**
5378  * mono_type_to_unmanaged:
5379  *
5380  * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
5381  * describing the underlying native reprensetation of the type.
5382  * 
5383  * In addition the value pointed by
5384  * "conv" will contain the kind of marshalling required for this
5385  * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
5386  */
5387 guint32
5388 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
5389                         gboolean unicode, MonoMarshalConv *conv) 
5390 {
5391         MonoMarshalConv dummy_conv;
5392         int t = type->type;
5393
5394         if (!conv)
5395                 conv = &dummy_conv;
5396
5397         *conv = MONO_MARSHAL_CONV_NONE;
5398
5399         if (type->byref)
5400                 return MONO_NATIVE_UINT;
5401
5402 handle_enum:
5403         switch (t) {
5404         case MONO_TYPE_BOOLEAN: 
5405                 if (mspec) {
5406                         switch (mspec->native) {
5407                         case MONO_NATIVE_VARIANTBOOL:
5408                                 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
5409                                 return MONO_NATIVE_VARIANTBOOL;
5410                         case MONO_NATIVE_BOOLEAN:
5411                                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
5412                                 return MONO_NATIVE_BOOLEAN;
5413                         case MONO_NATIVE_I1:
5414                         case MONO_NATIVE_U1:
5415                                 return mspec->native;
5416                         default:
5417                                 g_error ("cant marshal bool to native type %02x", mspec->native);
5418                         }
5419                 }
5420                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
5421                 return MONO_NATIVE_BOOLEAN;
5422         case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
5423         case MONO_TYPE_I1: return MONO_NATIVE_I1;
5424         case MONO_TYPE_U1: return MONO_NATIVE_U1;
5425         case MONO_TYPE_I2: return MONO_NATIVE_I2;
5426         case MONO_TYPE_U2: return MONO_NATIVE_U2;
5427         case MONO_TYPE_I4: return MONO_NATIVE_I4;
5428         case MONO_TYPE_U4: return MONO_NATIVE_U4;
5429         case MONO_TYPE_I8: return MONO_NATIVE_I8;
5430         case MONO_TYPE_U8: return MONO_NATIVE_U8;
5431         case MONO_TYPE_R4: return MONO_NATIVE_R4;
5432         case MONO_TYPE_R8: return MONO_NATIVE_R8;
5433         case MONO_TYPE_STRING:
5434                 if (mspec) {
5435                         switch (mspec->native) {
5436                         case MONO_NATIVE_BSTR:
5437                                 *conv = MONO_MARSHAL_CONV_STR_BSTR;
5438                                 return MONO_NATIVE_BSTR;
5439                         case MONO_NATIVE_LPSTR:
5440                                 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
5441                                 return MONO_NATIVE_LPSTR;
5442                         case MONO_NATIVE_LPWSTR:
5443                                 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
5444                                 return MONO_NATIVE_LPWSTR;
5445                         case MONO_NATIVE_LPTSTR:
5446                                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
5447                                 return MONO_NATIVE_LPTSTR;
5448                         case MONO_NATIVE_ANSIBSTR:
5449                                 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
5450                                 return MONO_NATIVE_ANSIBSTR;
5451                         case MONO_NATIVE_TBSTR:
5452                                 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
5453                                 return MONO_NATIVE_TBSTR;
5454                         case MONO_NATIVE_BYVALTSTR:
5455                                 if (unicode)
5456                                         *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
5457                                 else
5458                                         *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
5459                                 return MONO_NATIVE_BYVALTSTR;
5460                         default:
5461                                 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);
5462                         }
5463                 }       
5464                 if (unicode) {
5465                         *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
5466                         return MONO_NATIVE_LPWSTR; 
5467                 }
5468                 else {
5469                         *conv = MONO_MARSHAL_CONV_STR_LPSTR;
5470                         return MONO_NATIVE_LPSTR; 
5471                 }
5472         case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
5473         case MONO_TYPE_VALUETYPE: /*FIXME*/
5474                 if (type->data.klass->enumtype) {
5475                         t = mono_class_enum_basetype (type->data.klass)->type;
5476                         goto handle_enum;
5477                 }
5478                 if (type->data.klass == mono_defaults.handleref_class){
5479                         *conv = MONO_MARSHAL_CONV_HANDLEREF;
5480                         return MONO_NATIVE_INT;
5481                 }
5482                 return MONO_NATIVE_STRUCT;
5483         case MONO_TYPE_SZARRAY: 
5484         case MONO_TYPE_ARRAY: 
5485                 if (mspec) {
5486                         switch (mspec->native) {
5487                         case MONO_NATIVE_BYVALARRAY:
5488                                 if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
5489                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
5490                                 else
5491                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
5492                                 return MONO_NATIVE_BYVALARRAY;
5493                         case MONO_NATIVE_SAFEARRAY:
5494                                 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
5495                                 return MONO_NATIVE_SAFEARRAY;
5496                         case MONO_NATIVE_LPARRAY:                               
5497                                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
5498                                 return MONO_NATIVE_LPARRAY;
5499                         default:
5500                                 g_error ("cant marshal array as native type %02x", mspec->native);
5501                         }
5502                 }       
5503
5504                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
5505                 return MONO_NATIVE_LPARRAY;
5506         case MONO_TYPE_I: return MONO_NATIVE_INT;
5507         case MONO_TYPE_U: return MONO_NATIVE_UINT;
5508         case MONO_TYPE_CLASS: 
5509         case MONO_TYPE_OBJECT: {
5510                 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
5511                 if (mspec) {
5512                         switch (mspec->native) {
5513                         case MONO_NATIVE_STRUCT:
5514                                 return MONO_NATIVE_STRUCT;
5515                         case MONO_NATIVE_CUSTOM:
5516                                 return MONO_NATIVE_CUSTOM;
5517                         case MONO_NATIVE_INTERFACE:
5518                                 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
5519                                 return MONO_NATIVE_INTERFACE;
5520                         case MONO_NATIVE_IDISPATCH:
5521                                 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
5522                                 return MONO_NATIVE_IDISPATCH;
5523                         case MONO_NATIVE_IUNKNOWN:
5524                                 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
5525                                 return MONO_NATIVE_IUNKNOWN;
5526                         case MONO_NATIVE_FUNC:
5527                                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
5528                                                                                          type->data.klass == mono_defaults.delegate_class || 
5529                                                                                          type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
5530                                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
5531                                         return MONO_NATIVE_FUNC;
5532                                 }
5533                                 /* Fall through */
5534                         default:
5535                                 g_error ("cant marshal object as native type %02x", mspec->native);
5536                         }
5537                 }
5538                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
5539                                              type->data.klass == mono_defaults.delegate_class || 
5540                                              type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
5541                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
5542                         return MONO_NATIVE_FUNC;
5543                 }
5544                 if (mono_defaults.safehandle_class && type->data.klass == mono_defaults.safehandle_class){
5545                         *conv = MONO_MARSHAL_CONV_SAFEHANDLE;
5546                         return MONO_NATIVE_INT;
5547                 }
5548                 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
5549                 return MONO_NATIVE_STRUCT;
5550         }
5551         case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
5552         case MONO_TYPE_GENERICINST:
5553                 type = &type->data.generic_class->container_class->byval_arg;
5554                 t = type->type;
5555                 goto handle_enum;
5556         case MONO_TYPE_TYPEDBYREF:
5557         default:
5558                 g_error ("type 0x%02x not handled in marshal", t);
5559         }
5560         return MONO_NATIVE_MAX;
5561 }
5562
5563 const char*
5564 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
5565 {
5566         locator_t loc;
5567         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_FIELDMARSHAL];
5568
5569         if (!tdef->base)
5570                 return NULL;
5571
5572         loc.t = tdef;
5573         loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
5574         loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
5575
5576         /* FIXME: Index translation */
5577
5578         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5579                 return NULL;
5580
5581         return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
5582 }
5583
5584 MonoMethod*
5585 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
5586 {
5587         guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
5588
5589         switch (tok & MONO_METHODDEFORREF_MASK) {
5590         case MONO_METHODDEFORREF_METHODDEF:
5591                 return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
5592         case MONO_METHODDEFORREF_METHODREF:
5593                 return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
5594         }
5595         g_assert_not_reached ();
5596         return NULL;
5597 }
5598
5599 /*
5600  * mono_class_get_overrides_full:
5601  *
5602  *   Return the method overrides belonging to class @type_token in @overrides, and
5603  * the number of overrides in @num_overrides.
5604  *
5605  * Returns: TRUE on success, FALSE on failure.
5606  */
5607 gboolean
5608 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
5609                                MonoGenericContext *generic_context)
5610 {
5611         MonoError error;
5612         locator_t loc;
5613         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
5614         guint32 start, end;
5615         gint32 i, num;
5616         guint32 cols [MONO_METHODIMPL_SIZE];
5617         MonoMethod **result;
5618         gint32 ok = TRUE;
5619         
5620         *overrides = NULL;
5621         if (num_overrides)
5622                 *num_overrides = 0;
5623
5624         if (!tdef->base)
5625                 return TRUE;
5626
5627         loc.t = tdef;
5628         loc.col_idx = MONO_METHODIMPL_CLASS;
5629         loc.idx = mono_metadata_token_index (type_token);
5630
5631         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5632                 return TRUE;
5633
5634         start = loc.result;
5635         end = start + 1;
5636         /*
5637          * We may end up in the middle of the rows... 
5638          */
5639         while (start > 0) {
5640                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
5641                         start--;
5642                 else
5643                         break;
5644         }
5645         while (end < tdef->rows) {
5646                 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
5647                         end++;
5648                 else
5649                         break;
5650         }
5651         num = end - start;
5652         result = g_new (MonoMethod*, num * 2);
5653         for (i = 0; i < num; ++i) {
5654                 MonoMethod *method;
5655
5656                 if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
5657                         mono_error_cleanup (&error);
5658                         ok = FALSE;
5659                         break;
5660                 }
5661
5662                 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
5663                 method = method_from_method_def_or_ref (
5664                         image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
5665                 if (method == NULL)
5666                         ok = FALSE;
5667                 result [i * 2] = method;
5668                 method = method_from_method_def_or_ref (
5669                         image, cols [MONO_METHODIMPL_BODY], generic_context);
5670                 if (method == NULL)
5671                         ok = FALSE;
5672                 result [i * 2 + 1] = method;
5673         }
5674
5675         *overrides = result;
5676         if (num_overrides)
5677                 *num_overrides = num;
5678         return ok;
5679 }
5680
5681 /**
5682  * mono_guid_to_string:
5683  *
5684  * Converts a 16 byte Microsoft GUID to the standard string representation.
5685  */
5686 char *
5687 mono_guid_to_string (const guint8 *guid)
5688 {
5689         return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
5690                                 guid[3], guid[2], guid[1], guid[0],
5691                                 guid[5], guid[4],
5692                                 guid[7], guid[6],
5693                                 guid[8], guid[9],
5694                                 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
5695 }
5696
5697 static gboolean
5698 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
5699 {
5700         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
5701         guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
5702         guint32 i, token, found;
5703         MonoClass *klass, **res;
5704         GSList *cons = NULL, *tmp;
5705         MonoGenericContext *context = &container->context;
5706
5707         *constraints = NULL;
5708         found = 0;
5709         for (i = 0; i < tdef->rows; ++i) {
5710                 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
5711                 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
5712                         token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
5713                         klass = mono_class_get_full (image, token, context);
5714                         if (!klass) {
5715                                 g_slist_free (cons);
5716                                 return FALSE;
5717                         }
5718                         cons = g_slist_append (cons, klass);
5719                         ++found;
5720                 } else {
5721                         /* contiguous list finished */
5722                         if (found)
5723                                 break;
5724                 }
5725         }
5726         if (!found)
5727                 return TRUE;
5728         res = g_new0 (MonoClass*, found + 1);
5729         for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
5730                 res [i] = tmp->data;
5731         }
5732         g_slist_free (cons);
5733         *constraints = res;
5734         return TRUE;
5735 }
5736
5737 /*
5738  * mono_metadata_get_generic_param_row:
5739  *
5740  * @image:
5741  * @token: TypeOrMethodDef token, owner for GenericParam
5742  * @owner: coded token, set on return
5743  * 
5744  * Returns: 1-based row-id in the GenericParam table whose
5745  * owner is @token. 0 if not found.
5746  */
5747 guint32
5748 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
5749 {
5750         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
5751         locator_t loc;
5752
5753         g_assert (owner);
5754         if (!tdef->base)
5755                 return 0;
5756
5757         if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
5758                 *owner = MONO_TYPEORMETHOD_TYPE;
5759         else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
5760                 *owner = MONO_TYPEORMETHOD_METHOD;
5761         else {
5762                 g_error ("wrong token %x to get_generic_param_row", token);
5763                 return 0;
5764         }
5765         *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
5766
5767         loc.idx = *owner;
5768         loc.col_idx = MONO_GENERICPARAM_OWNER;
5769         loc.t = tdef;
5770
5771         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5772                 return 0;
5773
5774         /* Find the first entry by searching backwards */
5775         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
5776                 loc.result --;
5777
5778         return loc.result + 1;
5779 }
5780
5781 gboolean
5782 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
5783 {
5784         guint32 owner;
5785         return mono_metadata_get_generic_param_row (image, token, &owner);
5786 }
5787
5788 gboolean
5789 mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
5790                                               MonoGenericContainer *container)
5791 {
5792
5793         guint32 start_row, i, owner;
5794         if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
5795                 return TRUE;
5796         for (i = 0; i < container->type_argc; i++) {
5797                 if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container))
5798                         return FALSE;
5799         }
5800         return TRUE;
5801 }
5802
5803 /*
5804  * mono_metadata_load_generic_param_constraints:
5805  *
5806  * @image: metadata context
5807  * @token: metadata token to load the contraints, can be methodef or typedef.
5808  * @container: generic container to load into.
5809  *
5810  * Load the generic parameter constraints for the newly created generic type or method
5811  * represented by @token and @container.  The @container is the new container which has
5812  * been returned by a call to mono_metadata_load_generic_params() with this @token.
5813  */
5814 void
5815 mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
5816                                               MonoGenericContainer *container)
5817 {
5818         mono_metadata_load_generic_param_constraints_full (image, token, container);
5819         /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
5820 }
5821
5822 /*
5823  * mono_metadata_load_generic_params:
5824  *
5825  * Load the type parameters from the type or method definition @token.
5826  *
5827  * Use this method after parsing a type or method definition to figure out whether it's a generic
5828  * type / method.  When parsing a method definition, @parent_container points to the generic container
5829  * of the current class, if any.
5830  *
5831  * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5832  *       creating the type.
5833  *
5834  * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5835  *
5836  * LOCKING: Acquires the loader lock
5837  *
5838  */
5839 MonoGenericContainer *
5840 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
5841 {
5842         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
5843         guint32 cols [MONO_GENERICPARAM_SIZE];
5844         guint32 i, owner = 0, n;
5845         MonoGenericContainer *container;
5846         MonoGenericParamFull *params;
5847         MonoGenericContext *context;
5848
5849         if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
5850                 return NULL;
5851         mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
5852         params = NULL;
5853         n = 0;
5854         container = mono_image_alloc0 (image, sizeof (MonoGenericContainer));
5855         container->image = image;
5856         do {
5857                 n++;
5858                 params = g_realloc (params, sizeof (MonoGenericParamFull) * n);
5859                 memset (&params [n - 1], 0, sizeof (MonoGenericParamFull));
5860                 params [n - 1].param.owner = container;
5861                 params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
5862                 params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
5863                 params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
5864                 params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
5865                 if (params [n - 1].param.num != n - 1)
5866                         g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
5867                 if (++i > tdef->rows)
5868                         break;
5869                 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
5870         } while (cols [MONO_GENERICPARAM_OWNER] == owner);
5871
5872         container->type_argc = n;
5873         container->type_params = mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
5874         memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
5875         g_free (params);
5876         container->parent = parent_container;
5877
5878         if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
5879                 container->is_method = 1;
5880
5881         g_assert (container->parent == NULL || container->is_method);
5882
5883         context = &container->context;
5884         if (container->is_method) {
5885                 context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
5886                 context->method_inst = mono_get_shared_generic_inst (container);
5887         } else {
5888                 context->class_inst = mono_get_shared_generic_inst (container);
5889         }
5890
5891         return container;
5892 }
5893
5894 MonoGenericInst *
5895 mono_get_shared_generic_inst (MonoGenericContainer *container)
5896 {
5897         MonoType **type_argv;
5898         MonoType *helper;
5899         MonoGenericInst *nginst;
5900         int i;
5901
5902         type_argv = g_new0 (MonoType *, container->type_argc);
5903         helper = g_new0 (MonoType, container->type_argc);
5904
5905         for (i = 0; i < container->type_argc; i++) {
5906                 MonoType *t = &helper [i];
5907
5908                 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5909                 t->data.generic_param = mono_generic_container_get_param (container, i);
5910
5911                 type_argv [i] = t;
5912         }
5913
5914         nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
5915
5916         g_free (type_argv);
5917         g_free (helper);
5918
5919         return nginst;
5920 }
5921
5922 /**
5923  * mono_type_is_byref:
5924  * @type: the MonoType operated on
5925  *
5926  * Returns: #TRUE if @type represents a type passed by reference,
5927  * #FALSE otherwise.
5928  */
5929 gboolean
5930 mono_type_is_byref (MonoType *type)
5931 {
5932         return type->byref;
5933 }
5934
5935 /**
5936  * mono_type_get_type:
5937  * @type: the MonoType operated on
5938  *
5939  * Returns: the IL type value for @type. This is one of the MonoTypeEnum
5940  * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
5941  */
5942 int
5943 mono_type_get_type (MonoType *type)
5944 {
5945         return type->type;
5946 }
5947
5948 /**
5949  * mono_type_get_signature:
5950  * @type: the MonoType operated on
5951  *
5952  * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
5953  *
5954  * Returns: the MonoMethodSignature pointer that describes the signature
5955  * of the function pointer @type represents.
5956  */
5957 MonoMethodSignature*
5958 mono_type_get_signature (MonoType *type)
5959 {
5960         g_assert (type->type == MONO_TYPE_FNPTR);
5961         return type->data.method;
5962 }
5963
5964 /**
5965  * mono_type_get_class:
5966  * @type: the MonoType operated on
5967  *
5968  * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
5969  * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
5970  * instead
5971  *
5972  * Returns: the MonoClass pointer that describes the class that @type represents.
5973  */
5974 MonoClass*
5975 mono_type_get_class (MonoType *type)
5976 {
5977         /* FIXME: review the runtime users before adding the assert here */
5978         return type->data.klass;
5979 }
5980
5981 /**
5982  * mono_type_get_array_type:
5983  * @type: the MonoType operated on
5984  *
5985  * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
5986  *
5987  * Returns: a MonoArrayType struct describing the array type that @type
5988  * represents. The info includes details such as rank, array element type
5989  * and the sizes and bounds of multidimensional arrays.
5990  */
5991 MonoArrayType*
5992 mono_type_get_array_type (MonoType *type)
5993 {
5994         return type->data.array;
5995 }
5996
5997 /**
5998  * mono_type_get_ptr_type:
5999  * @type: the MonoType operated on
6000  *
6001  * It is only valid to call this function if @type is a MONO_TYPE_PTR.
6002  * instead
6003  *
6004  * Returns: the MonoType pointer that describes the type that @type
6005  * represents a pointer to.
6006  */
6007 MonoType*
6008 mono_type_get_ptr_type (MonoType *type)
6009 {
6010         g_assert (type->type == MONO_TYPE_PTR);
6011         return type->data.type;
6012 }
6013
6014 MonoClass*
6015 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
6016 {
6017         /* FIXME: implement */
6018         return NULL;
6019 }
6020
6021 /**
6022  * mono_type_is_struct:
6023  * @type: the MonoType operated on
6024  *
6025  * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
6026  * or a basic type like System.Int32. #FALSE otherwise.
6027  */
6028 mono_bool
6029 mono_type_is_struct (MonoType *type)
6030 {
6031         return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
6032                 !type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
6033                 ((type->type == MONO_TYPE_GENERICINST) && 
6034                 mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
6035                 !type->data.generic_class->container_class->enumtype)));
6036 }
6037
6038 /**
6039  * mono_type_is_void:
6040  * @type: the MonoType operated on
6041  *
6042  * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
6043  */
6044 mono_bool
6045 mono_type_is_void (MonoType *type)
6046 {
6047         return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
6048 }
6049
6050 /**
6051  * mono_type_is_pointer:
6052  * @type: the MonoType operated on
6053  *
6054  * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
6055  */
6056 mono_bool
6057 mono_type_is_pointer (MonoType *type)
6058 {
6059         return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
6060                 || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6061                 (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
6062                 (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
6063                 (type->type == MONO_TYPE_FNPTR)));
6064 }
6065
6066 /**
6067  * mono_type_is_reference:
6068  * @type: the MonoType operated on
6069  *
6070  * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
6071  */
6072 mono_bool
6073 mono_type_is_reference (MonoType *type)
6074 {
6075         return (type && (((type->type == MONO_TYPE_STRING) ||
6076                 (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6077                 (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
6078                 ((type->type == MONO_TYPE_GENERICINST) &&
6079                 !mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
6080 }
6081
6082 /**
6083  * mono_signature_get_return_type:
6084  * @sig: the method signature inspected
6085  *
6086  * Returns: the return type of the method signature @sig
6087  */
6088 MonoType*
6089 mono_signature_get_return_type (MonoMethodSignature *sig)
6090 {
6091         return sig->ret;
6092 }
6093
6094 /**
6095  * mono_signature_get_params:
6096  * @sig: the method signature inspected
6097  * #iter: pointer to an iterator
6098  *
6099  * Iterates over the parameters for the method signature @sig.
6100  * A void* pointer must be initualized to #NULL to start the iteration
6101  * and it's address is passed to this function repeteadly until it returns
6102  * #NULL.
6103  *
6104  * Returns: the next parameter type of the method signature @sig,
6105  * #NULL when finished.
6106  */
6107 MonoType*
6108 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
6109 {
6110         MonoType** type;
6111         if (!iter)
6112                 return NULL;
6113         if (!*iter) {
6114                 /* start from the first */
6115                 if (sig->param_count) {
6116                         *iter = &sig->params [0];
6117                         return sig->params [0];
6118                 } else {
6119                         /* no method */
6120                         return NULL;
6121                 }
6122         }
6123         type = *iter;
6124         type++;
6125         if (type < &sig->params [sig->param_count]) {
6126                 *iter = type;
6127                 return *type;
6128         }
6129         return NULL;
6130 }
6131
6132 /**
6133  * mono_signature_get_param_count:
6134  * @sig: the method signature inspected
6135  *
6136  * Returns: the number of parameters in the method signature @sig.
6137  */
6138 guint32
6139 mono_signature_get_param_count (MonoMethodSignature *sig)
6140 {
6141         return sig->param_count;
6142 }
6143
6144 /**
6145  * mono_signature_get_call_conv:
6146  * @sig: the method signature inspected
6147  *
6148  * Returns: the call convention of the method signature @sig.
6149  */
6150 guint32
6151 mono_signature_get_call_conv (MonoMethodSignature *sig)
6152 {
6153         return sig->call_convention;
6154 }
6155
6156 /**
6157  * mono_signature_vararg_start:
6158  * @sig: the method signature inspected
6159  *
6160  * Returns: the number of the first vararg parameter in the
6161  * method signature @sig. -1 if this is not a vararg signature.
6162  */
6163 int
6164 mono_signature_vararg_start (MonoMethodSignature *sig)
6165 {
6166         return sig->sentinelpos;
6167 }
6168
6169 /**
6170  * mono_signature_is_instance:
6171  * @sig: the method signature inspected
6172  *
6173  * Returns: #TRUE if this the method signature @sig has an implicit
6174  * first instance argument. #FALSE otherwise.
6175  */
6176 gboolean
6177 mono_signature_is_instance (MonoMethodSignature *sig)
6178 {
6179         return sig->hasthis;
6180 }
6181
6182 /**
6183  * mono_signature_explicit_this:
6184  * @sig: the method signature inspected
6185  *
6186  * Returns: #TRUE if this the method signature @sig has an explicit
6187  * instance argument. #FALSE otherwise.
6188  */
6189 gboolean
6190 mono_signature_explicit_this (MonoMethodSignature *sig)
6191 {
6192         return sig->explicit_this;
6193 }
6194
6195 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6196 guint
6197 mono_aligned_addr_hash (gconstpointer ptr)
6198 {
6199         return GPOINTER_TO_UINT (ptr) >> 3;
6200 }
6201
6202 /*
6203  * If @field belongs to an inflated generic class, return the corresponding field of the
6204  * generic type definition class.
6205  */
6206 MonoClassField*
6207 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
6208 {
6209         MonoClass *gtd;
6210         int offset;
6211
6212         if (!field->parent->generic_class)
6213                 return field;
6214
6215         gtd = field->parent->generic_class->container_class;
6216         offset = field - field->parent->fields;
6217         return gtd->fields + offset;
6218 }
6219
6220 /*
6221  * If @event belongs to an inflated generic class, return the corresponding event of the
6222  * generic type definition class.
6223  */
6224 MonoEvent*
6225 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
6226 {
6227         MonoClass *gtd;
6228         int offset;
6229
6230         if (!event->parent->generic_class)
6231                 return event;
6232
6233         gtd = event->parent->generic_class->container_class;
6234         offset = event - event->parent->ext->events;
6235         return gtd->ext->events + offset;
6236 }
6237
6238 /*
6239  * If @property belongs to an inflated generic class, return the corresponding property of the
6240  * generic type definition class.
6241  */
6242 MonoProperty*
6243 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
6244 {
6245         MonoClass *gtd;
6246         int offset;
6247
6248         if (!property->parent->generic_class)
6249                 return property;
6250
6251         gtd = property->parent->generic_class->container_class;
6252         offset = property - property->parent->ext->properties;
6253         return gtd->ext->properties + offset;
6254 }
6255