[runtime] Use IOAMP-aware method of looking for domain configuration file
[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 "debug-helpers.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 void free_generic_inst (MonoGenericInst *ginst);
48 static void free_generic_class (MonoGenericClass *ginst);
49 static void free_inflated_method (MonoMethodInflated *method);
50 static void free_inflated_signature (MonoInflatedMethodSignature *sig);
51 static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
52
53 /*
54  * This enumeration is used to describe the data types in the metadata
55  * tables
56  */
57 enum {
58         MONO_MT_END,
59
60         /* Sized elements */
61         MONO_MT_UINT32,
62         MONO_MT_UINT16,
63         MONO_MT_UINT8,
64
65         /* Index into Blob heap */
66         MONO_MT_BLOB_IDX,
67
68         /* Index into String heap */
69         MONO_MT_STRING_IDX,
70
71         /* GUID index */
72         MONO_MT_GUID_IDX,
73
74         /* Pointer into a table */
75         MONO_MT_TABLE_IDX,
76
77         /* HasConstant:Parent pointer (Param, Field or Property) */
78         MONO_MT_CONST_IDX,
79
80         /* HasCustomAttribute index.  Indexes any table except CustomAttribute */
81         MONO_MT_HASCAT_IDX,
82         
83         /* CustomAttributeType encoded index */
84         MONO_MT_CAT_IDX,
85
86         /* HasDeclSecurity index: TypeDef Method or Assembly */
87         MONO_MT_HASDEC_IDX,
88
89         /* Implementation coded index: File, Export AssemblyRef */
90         MONO_MT_IMPL_IDX,
91
92         /* HasFieldMarshal coded index: Field or Param table */
93         MONO_MT_HFM_IDX,
94
95         /* MemberForwardedIndex: Field or Method */
96         MONO_MT_MF_IDX,
97
98         /* TypeDefOrRef coded index: typedef, typeref, typespec */
99         MONO_MT_TDOR_IDX,
100
101         /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
102         MONO_MT_MRP_IDX,
103
104         /* MethodDefOrRef coded index: Method or Member Ref table */
105         MONO_MT_MDOR_IDX,
106
107         /* HasSemantic coded index: Event or Property */
108         MONO_MT_HS_IDX,
109
110         /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
111         MONO_MT_RS_IDX
112 };
113
114 const static unsigned char TableSchemas [] = {
115 #define ASSEMBLY_SCHEMA_OFFSET 0
116         MONO_MT_UINT32,     /* "HashId" }, */
117         MONO_MT_UINT16,     /* "Major" },  */
118         MONO_MT_UINT16,     /* "Minor" }, */
119         MONO_MT_UINT16,     /* "BuildNumber" }, */
120         MONO_MT_UINT16,     /* "RevisionNumber" }, */
121         MONO_MT_UINT32,     /* "Flags" }, */
122         MONO_MT_BLOB_IDX,   /* "PublicKey" }, */
123         MONO_MT_STRING_IDX, /* "Name" }, */
124         MONO_MT_STRING_IDX, /* "Culture" }, */
125         MONO_MT_END,
126
127 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
128         MONO_MT_UINT32,     /* "OSPlatformID" }, */
129         MONO_MT_UINT32,     /* "OSMajor" }, */
130         MONO_MT_UINT32,     /* "OSMinor" }, */
131         MONO_MT_END,
132
133 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
134         MONO_MT_UINT32,     /* "Processor" }, */
135         MONO_MT_END,
136
137 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
138         MONO_MT_UINT16,     /* "Major" }, */
139         MONO_MT_UINT16,     /* "Minor" }, */
140         MONO_MT_UINT16,     /* "Build" }, */
141         MONO_MT_UINT16,     /* "Revision" }, */
142         MONO_MT_UINT32,     /* "Flags" }, */
143         MONO_MT_BLOB_IDX,   /* "PublicKeyOrToken" }, */
144         MONO_MT_STRING_IDX, /* "Name" }, */
145         MONO_MT_STRING_IDX, /* "Culture" }, */
146         MONO_MT_BLOB_IDX,   /* "HashValue" }, */
147         MONO_MT_END,
148
149 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
150         MONO_MT_UINT32,     /* "OSPlatformID" }, */
151         MONO_MT_UINT32,     /* "OSMajorVersion" }, */
152         MONO_MT_UINT32,     /* "OSMinorVersion" }, */
153         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
154         MONO_MT_END,
155
156 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
157         MONO_MT_UINT32,     /* "Processor" }, */
158         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
159         MONO_MT_END,
160
161 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
162         MONO_MT_UINT16,     /* "PackingSize" }, */
163         MONO_MT_UINT32,     /* "ClassSize" }, */
164         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
165         MONO_MT_END,
166
167 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
168         MONO_MT_UINT8,      /* "Type" }, */
169         MONO_MT_UINT8,      /* "PaddingZero" }, */
170         MONO_MT_CONST_IDX,  /* "Parent" }, */
171         MONO_MT_BLOB_IDX,   /* "Value" }, */
172         MONO_MT_END,
173
174 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
175         MONO_MT_HASCAT_IDX, /* "Parent" }, */
176         MONO_MT_CAT_IDX,    /* "Type" }, */
177         MONO_MT_BLOB_IDX,   /* "Value" }, */
178         MONO_MT_END,
179
180 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
181         MONO_MT_UINT16,     /* "Action" }, */
182         MONO_MT_HASDEC_IDX, /* "Parent" }, */
183         MONO_MT_BLOB_IDX,   /* "PermissionSet" }, */
184         MONO_MT_END,
185
186 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
187         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
188         MONO_MT_TABLE_IDX,  /* "EventList:Event" }, */
189         MONO_MT_END,
190
191 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
192         MONO_MT_UINT16,     /* "EventFlags#EventAttribute" }, */
193         MONO_MT_STRING_IDX, /* "Name" }, */
194         MONO_MT_TDOR_IDX,  /* "EventType" }, TypeDef or TypeRef or TypeSpec  */
195         MONO_MT_END,
196
197 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
198         MONO_MT_TABLE_IDX,  /* "Event" }, */
199         MONO_MT_END,
200
201 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
202         MONO_MT_UINT32,     /* "Flags" }, */
203         MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
204         MONO_MT_STRING_IDX, /* "TypeName" }, */
205         MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
206         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
207         MONO_MT_END,
208
209 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
210         MONO_MT_UINT16,     /* "Flags" }, */
211         MONO_MT_STRING_IDX, /* "Name" }, */
212         MONO_MT_BLOB_IDX,   /* "Signature" }, */
213         MONO_MT_END,
214
215 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
216         MONO_MT_UINT32,     /* "Offset" }, */
217         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
218         MONO_MT_END,
219
220 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
221         MONO_MT_HFM_IDX,    /* "Parent" }, */
222         MONO_MT_BLOB_IDX,   /* "NativeType" }, */
223         MONO_MT_END,
224
225 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
226         MONO_MT_UINT32,     /* "RVA" }, */
227         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
228         MONO_MT_END,
229
230 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
231         MONO_MT_TABLE_IDX,  /* "Field" }, */
232         MONO_MT_END,
233
234 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
235         MONO_MT_UINT32,     /* "Flags" }, */
236         MONO_MT_STRING_IDX, /* "Name" }, */
237         MONO_MT_BLOB_IDX,   /* "Value" },  */
238         MONO_MT_END,
239
240 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
241         MONO_MT_UINT16,     /* "MappingFlag" }, */
242         MONO_MT_MF_IDX,     /* "MemberForwarded" }, */
243         MONO_MT_STRING_IDX, /* "ImportName" }, */
244         MONO_MT_TABLE_IDX,  /* "ImportScope:ModuleRef" }, */
245         MONO_MT_END,
246
247 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
248         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" },  */
249         MONO_MT_TDOR_IDX,  /* "Interface=TypeDefOrRef" }, */
250         MONO_MT_END,
251
252 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
253         MONO_MT_UINT32,     /* "Offset" }, */
254         MONO_MT_UINT32,     /* "Flags" }, */
255         MONO_MT_STRING_IDX, /* "Name" }, */
256         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
257         MONO_MT_END,
258
259 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
260         MONO_MT_MRP_IDX,    /* "Class" }, */
261         MONO_MT_STRING_IDX, /* "Name" }, */
262         MONO_MT_BLOB_IDX,   /* "Signature" }, */
263         MONO_MT_END,
264
265 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
266         MONO_MT_UINT32,     /* "RVA" }, */
267         MONO_MT_UINT16,     /* "ImplFlags#MethodImplAttributes" }, */
268         MONO_MT_UINT16,     /* "Flags#MethodAttribute" }, */
269         MONO_MT_STRING_IDX, /* "Name" }, */
270         MONO_MT_BLOB_IDX,   /* "Signature" }, */
271         MONO_MT_TABLE_IDX,  /* "ParamList:Param" }, */
272         MONO_MT_END,
273
274 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
275         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" }, */
276         MONO_MT_MDOR_IDX,   /* "MethodBody" }, */
277         MONO_MT_MDOR_IDX,   /* "MethodDeclaration" }, */
278         MONO_MT_END,
279
280 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
281         MONO_MT_UINT16,     /* "MethodSemantic" }, */
282         MONO_MT_TABLE_IDX,  /* "Method:Method" }, */
283         MONO_MT_HS_IDX,     /* "Association" }, */
284         MONO_MT_END,
285
286 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
287         MONO_MT_TABLE_IDX,  /* "Method" }, */
288         MONO_MT_END,
289
290 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
291         MONO_MT_UINT16,     /* "Generation" }, */
292         MONO_MT_STRING_IDX, /* "Name" }, */
293         MONO_MT_GUID_IDX,   /* "MVID" }, */
294         MONO_MT_GUID_IDX,   /* "EncID" }, */
295         MONO_MT_GUID_IDX,   /* "EncBaseID" }, */
296         MONO_MT_END,
297
298 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
299         MONO_MT_STRING_IDX, /* "Name" }, */
300         MONO_MT_END,
301
302 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
303         MONO_MT_TABLE_IDX,  /* "NestedClass:TypeDef" }, */
304         MONO_MT_TABLE_IDX,  /* "EnclosingClass:TypeDef" }, */
305         MONO_MT_END,
306
307 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
308         MONO_MT_UINT16,     /* "Flags" }, */
309         MONO_MT_UINT16,     /* "Sequence" }, */
310         MONO_MT_STRING_IDX, /* "Name" }, */
311         MONO_MT_END,
312
313 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
314         MONO_MT_TABLE_IDX,  /* "Param" }, */
315         MONO_MT_END,
316
317 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
318         MONO_MT_UINT16,     /* "Flags" }, */
319         MONO_MT_STRING_IDX, /* "Name" }, */
320         MONO_MT_BLOB_IDX,   /* "Type" }, */
321         MONO_MT_END,
322
323 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
324         MONO_MT_TABLE_IDX, /* "Property" }, */
325         MONO_MT_END,
326
327 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
328         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
329         MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
330         MONO_MT_END,
331
332 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
333         MONO_MT_BLOB_IDX,   /* "Signature" }, */
334         MONO_MT_END,
335
336 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
337         MONO_MT_UINT32,     /* "Flags" }, */
338         MONO_MT_STRING_IDX, /* "Name" }, */
339         MONO_MT_STRING_IDX, /* "Namespace" }, */
340         MONO_MT_TDOR_IDX,   /* "Extends" }, */
341         MONO_MT_TABLE_IDX,  /* "FieldList:Field" }, */
342         MONO_MT_TABLE_IDX,  /* "MethodList:Method" }, */
343         MONO_MT_END,
344
345 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
346         MONO_MT_RS_IDX,     /* "ResolutionScope=ResolutionScope" }, */
347         MONO_MT_STRING_IDX, /* "Name" }, */
348         MONO_MT_STRING_IDX, /* "Namespace" }, */
349         MONO_MT_END,
350
351 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
352         MONO_MT_BLOB_IDX,   /* "Signature" }, */
353         MONO_MT_END,
354
355 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
356         MONO_MT_UINT16,     /* "Number" }, */
357         MONO_MT_UINT16,     /* "Flags" }, */
358         MONO_MT_TABLE_IDX,  /* "Owner" },  TypeDef or MethodDef */
359         MONO_MT_STRING_IDX, /* "Name" }, */
360         MONO_MT_END,
361
362 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
363         MONO_MT_MDOR_IDX,   /* "Method" }, */
364         MONO_MT_BLOB_IDX,   /* "Signature" }, */
365         MONO_MT_END,
366
367 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
368         MONO_MT_TABLE_IDX,  /* "GenericParam" }, */
369         MONO_MT_TDOR_IDX,   /* "Constraint" }, */
370         MONO_MT_END,
371
372 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
373         MONO_MT_END
374 };
375
376 /* Must be the same order as MONO_TABLE_* */
377 const static unsigned char
378 table_description [] = {
379         MODULE_SCHEMA_OFFSET,
380         TYPEREF_SCHEMA_OFFSET,
381         TYPEDEF_SCHEMA_OFFSET,
382         FIELD_POINTER_SCHEMA_OFFSET,
383         FIELD_SCHEMA_OFFSET,
384         METHOD_POINTER_SCHEMA_OFFSET,
385         METHOD_SCHEMA_OFFSET,
386         PARAM_POINTER_SCHEMA_OFFSET,
387         PARAM_SCHEMA_OFFSET,
388         IFACEMAP_SCHEMA_OFFSET,
389         MEMBERREF_SCHEMA_OFFSET, /* 0xa */
390         CONSTANT_SCHEMA_OFFSET,
391         CUSTOM_ATTR_SCHEMA_OFFSET,
392         FIELD_MARSHAL_SCHEMA_OFFSET,
393         DECL_SEC_SCHEMA_OFFSET,
394         CLASS_LAYOUT_SCHEMA_OFFSET,
395         FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
396         STDALON_SIG_SCHEMA_OFFSET,
397         EVENTMAP_SCHEMA_OFFSET,
398         EVENT_POINTER_SCHEMA_OFFSET,
399         EVENT_SCHEMA_OFFSET,
400         PROPERTY_MAP_SCHEMA_OFFSET,
401         PROPERTY_POINTER_SCHEMA_OFFSET,
402         PROPERTY_SCHEMA_OFFSET,
403         METHOD_SEMA_SCHEMA_OFFSET,
404         METHOD_IMPL_SCHEMA_OFFSET,
405         MODULEREF_SCHEMA_OFFSET, /* 0x1a */
406         TYPESPEC_SCHEMA_OFFSET,
407         IMPLMAP_SCHEMA_OFFSET,
408         FIELD_RVA_SCHEMA_OFFSET,
409         NULL_SCHEMA_OFFSET,
410         NULL_SCHEMA_OFFSET,
411         ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
412         ASSEMBLYPROC_SCHEMA_OFFSET,
413         ASSEMBLYOS_SCHEMA_OFFSET,
414         ASSEMBLYREF_SCHEMA_OFFSET,
415         ASSEMBLYREFPROC_SCHEMA_OFFSET,
416         ASSEMBLYREFOS_SCHEMA_OFFSET,
417         FILE_SCHEMA_OFFSET,
418         EXPORTED_TYPE_SCHEMA_OFFSET,
419         MANIFEST_SCHEMA_OFFSET,
420         NESTED_CLASS_SCHEMA_OFFSET,
421         GENPARAM_SCHEMA_OFFSET, /* 0x2a */
422         METHOD_SPEC_SCHEMA_OFFSET,
423         GEN_CONSTRAINT_SCHEMA_OFFSET
424 };
425
426 #ifdef HAVE_ARRAY_ELEM_INIT
427 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
428 #define MSGSTRFIELD1(line) str##line
429 static const struct msgstr_t {
430 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
431 #include "mono/cil/tables.def"
432 #undef TABLEDEF
433 } tablestr = {
434 #define TABLEDEF(a,b) b,
435 #include "mono/cil/tables.def"
436 #undef TABLEDEF
437 };
438 static const gint16 tableidx [] = {
439 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
440 #include "mono/cil/tables.def"
441 #undef TABLEDEF
442 };
443
444 #else
445 #define TABLEDEF(a,b) b,
446 static const char* const
447 mono_tables_names [] = {
448 #include "mono/cil/tables.def"
449         NULL
450 };
451
452 #endif
453
454 /**
455  * mono_meta_table_name:
456  * @table: table index
457  *
458  * Returns the name of the given ECMA metadata logical format table
459  * as described in ECMA 335, Partition II, Section 22.
460  * 
461  * Returns: the name for the @table index
462  */
463 const char *
464 mono_meta_table_name (int table)
465 {
466         if ((table < 0) || (table > MONO_TABLE_LAST))
467                 return "";
468
469 #ifdef HAVE_ARRAY_ELEM_INIT
470         return (const char*)&tablestr + tableidx [table];
471 #else
472         return mono_tables_names [table];
473 #endif
474 }
475
476 /* The guy who wrote the spec for this should not be allowed near a
477  * computer again.
478  
479 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
480 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
481 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
482 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
483 inverse of this mapping.
484
485  */
486 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
487 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
488
489 /* Reference: Partition II - 23.2.6 */
490 /*
491  * mono_metadata_compute_size:
492  * @meta: metadata context
493  * @tableindex: metadata table number
494  * @result_bitfield: pointer to guint32 where to store additional info
495  * 
496  * mono_metadata_compute_size() computes the lenght in bytes of a single
497  * row in a metadata table. The size of each column is encoded in the
498  * @result_bitfield return value along with the number of columns in the table.
499  * the resulting bitfield should be handed to the mono_metadata_table_size()
500  * and mono_metadata_table_count() macros.
501  * This is a Mono runtime internal only function.
502  */
503 int
504 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
505 {
506         guint32 bitfield = 0;
507         int size = 0, field_size = 0;
508         int i, n, code;
509         int shift = 0;
510         const unsigned char *description = TableSchemas + table_description [tableindex];
511
512         for (i = 0; (code = description [i]) != MONO_MT_END; i++){
513                 switch (code){
514                 case MONO_MT_UINT32:
515                         field_size = 4; break;
516                         
517                 case MONO_MT_UINT16:
518                         field_size = 2; break;
519                         
520                 case MONO_MT_UINT8:
521                         field_size = 1; break;
522                         
523                 case MONO_MT_BLOB_IDX:
524                         field_size = meta->idx_blob_wide ? 4 : 2; break;
525                         
526                 case MONO_MT_STRING_IDX:
527                         field_size = meta->idx_string_wide ? 4 : 2; break;
528                         
529                 case MONO_MT_GUID_IDX:
530                         field_size = meta->idx_guid_wide ? 4 : 2; break;
531
532                 case MONO_MT_TABLE_IDX:
533                         /* Uhm, a table index can point to other tables besides the current one
534                          * so, it's not correct to use the rowcount of the current table to
535                          * get the size for this column - lupus 
536                          */
537                         switch (tableindex) {
538                         case MONO_TABLE_ASSEMBLYREFOS:
539                                 g_assert (i == 3);
540                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
541                         case MONO_TABLE_ASSEMBLYREFPROCESSOR:
542                                 g_assert (i == 1);
543                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
544                         case MONO_TABLE_CLASSLAYOUT:
545                                 g_assert (i == 2);
546                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
547                         case MONO_TABLE_EVENTMAP:
548                                 g_assert (i == 0 || i == 1);
549                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
550                                         idx_size(MONO_TABLE_TYPEDEF); 
551                                 break;
552                         case MONO_TABLE_EVENT_POINTER:
553                                 g_assert (i == 0);
554                                 field_size = idx_size (MONO_TABLE_EVENT); break;
555                         case MONO_TABLE_EXPORTEDTYPE:
556                                 g_assert (i == 1);
557                                 /* the index is in another metadata file, so it must be 4 */
558                                 field_size = 4; break;
559                         case MONO_TABLE_FIELDLAYOUT:
560                                 g_assert (i == 1);
561                                 field_size = idx_size (MONO_TABLE_FIELD); break;
562                         case MONO_TABLE_FIELDRVA:
563                                 g_assert (i == 1);
564                                 field_size = idx_size (MONO_TABLE_FIELD); break;
565                         case MONO_TABLE_FIELD_POINTER:
566                                 g_assert (i == 0);
567                                 field_size = idx_size (MONO_TABLE_FIELD); break;
568                         case MONO_TABLE_IMPLMAP:
569                                 g_assert (i == 3);
570                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
571                         case MONO_TABLE_INTERFACEIMPL:
572                                 g_assert (i == 0);
573                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
574                         case MONO_TABLE_METHOD:
575                                 g_assert (i == 5);
576                                 field_size = idx_size (MONO_TABLE_PARAM); break;
577                         case MONO_TABLE_METHODIMPL:
578                                 g_assert (i == 0);
579                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
580                         case MONO_TABLE_METHODSEMANTICS:
581                                 g_assert (i == 1);
582                                 field_size = idx_size (MONO_TABLE_METHOD); break;
583                         case MONO_TABLE_METHOD_POINTER:
584                                 g_assert (i == 0);
585                                 field_size = idx_size (MONO_TABLE_METHOD); break;
586                         case MONO_TABLE_NESTEDCLASS:
587                                 g_assert (i == 0 || i == 1);
588                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
589                         case MONO_TABLE_PARAM_POINTER:
590                                 g_assert (i == 0);
591                                 field_size = idx_size (MONO_TABLE_PARAM); break;
592                         case MONO_TABLE_PROPERTYMAP:
593                                 g_assert (i == 0 || i == 1);
594                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
595                                         idx_size(MONO_TABLE_TYPEDEF); 
596                                 break;
597                         case MONO_TABLE_PROPERTY_POINTER:
598                                 g_assert (i == 0);
599                                 field_size = idx_size (MONO_TABLE_PROPERTY); break;
600                         case MONO_TABLE_TYPEDEF:
601                                 g_assert (i == 4 || i == 5);
602                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
603                                         idx_size(MONO_TABLE_METHOD);
604                                 break;
605                         case MONO_TABLE_GENERICPARAM:
606                                 g_assert (i == 2);
607                                 n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
608                                 /*This is a coded token for 2 tables, so takes 1 bit */
609                                 field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
610                                 break;
611                         case MONO_TABLE_GENERICPARAMCONSTRAINT:
612                                 g_assert (i == 0);
613                                 field_size = idx_size (MONO_TABLE_GENERICPARAM);
614                                 break;
615                                 
616                         default:
617                                 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
618                         }
619                         break;
620
621                         /*
622                          * HasConstant: ParamDef, FieldDef, Property
623                          */
624                 case MONO_MT_CONST_IDX:
625                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
626                                  meta->tables [MONO_TABLE_FIELD].rows);
627                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
628
629                         /* 2 bits to encode tag */
630                         field_size = rtsize (n, 16-2);
631                         break;
632
633                         /*
634                          * HasCustomAttribute: points to any table but
635                          * itself.
636                          */
637                 case MONO_MT_HASCAT_IDX:
638                         /*
639                          * We believe that since the signature and
640                          * permission are indexing the Blob heap,
641                          * we should consider the blob size first
642                          */
643                         /* I'm not a believer - lupus
644                         if (meta->idx_blob_wide){
645                                 field_size = 4;
646                                 break;
647                         }*/
648                         
649                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
650                                  meta->tables [MONO_TABLE_FIELD].rows);
651                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
652                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
653                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
654                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
655                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
656                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
657                         n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
658                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
659                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
660                         n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
661                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
662                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
663                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
664                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
665                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
666                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
667                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
668
669                         /* 5 bits to encode */
670                         field_size = rtsize (n, 16-5);
671                         break;
672
673                         /*
674                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
675                          * MemberRef and String.  
676                          */
677                 case MONO_MT_CAT_IDX:
678                         /* String is a heap, if it is wide, we know the size */
679                         /* See above, nope. 
680                         if (meta->idx_string_wide){
681                                 field_size = 4;
682                                 break;
683                         }*/
684                         
685                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
686                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
687                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
688                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
689
690                         /* 3 bits to encode */
691                         field_size = rtsize (n, 16-3);
692                         break;
693
694                         /*
695                          * HasDeclSecurity: Typedef, MethodDef, Assembly
696                          */
697                 case MONO_MT_HASDEC_IDX:
698                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
699                                  meta->tables [MONO_TABLE_METHOD].rows);
700                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
701
702                         /* 2 bits to encode */
703                         field_size = rtsize (n, 16-2);
704                         break;
705
706                         /*
707                          * Implementation: File, AssemblyRef, ExportedType
708                          */
709                 case MONO_MT_IMPL_IDX:
710                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
711                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
712                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
713
714                         /* 2 bits to encode tag */
715                         field_size = rtsize (n, 16-2);
716                         break;
717
718                         /*
719                          * HasFieldMarshall: FieldDef, ParamDef
720                          */
721                 case MONO_MT_HFM_IDX:
722                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
723                                  meta->tables [MONO_TABLE_PARAM].rows);
724
725                         /* 1 bit used to encode tag */
726                         field_size = rtsize (n, 16-1);
727                         break;
728
729                         /*
730                          * MemberForwarded: FieldDef, MethodDef
731                          */
732                 case MONO_MT_MF_IDX:
733                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
734                                  meta->tables [MONO_TABLE_METHOD].rows);
735
736                         /* 1 bit used to encode tag */
737                         field_size = rtsize (n, 16-1);
738                         break;
739
740                         /*
741                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
742                          * LAMESPEC
743                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
744                          */
745                 case MONO_MT_TDOR_IDX:
746                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
747                                  meta->tables [MONO_TABLE_TYPEREF].rows);
748                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
749
750                         /* 2 bits to encode */
751                         field_size = rtsize (n, 16-2);
752                         break;
753
754                         /*
755                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
756                          */
757                 case MONO_MT_MRP_IDX:
758                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
759                                  meta->tables [MONO_TABLE_TYPEREF].rows);
760                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
761                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
762                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
763                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
764
765                         /* 3 bits to encode */
766                         field_size = rtsize (n, 16 - 3);
767                         break;
768                         
769                         /*
770                          * MethodDefOrRef: MethodDef, MemberRef
771                          */
772                 case MONO_MT_MDOR_IDX:
773                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
774                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
775
776                         /* 1 bit used to encode tag */
777                         field_size = rtsize (n, 16-1);
778                         break;
779                         
780                         /*
781                          * HasSemantics: Property, Event
782                          */
783                 case MONO_MT_HS_IDX:
784                         n = MAX (meta->tables [MONO_TABLE_PROPERTY].rows,
785                                  meta->tables [MONO_TABLE_EVENT].rows);
786
787                         /* 1 bit used to encode tag */
788                         field_size = rtsize (n, 16-1);
789                         break;
790
791                         /*
792                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
793                          */
794                 case MONO_MT_RS_IDX:
795                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
796                                  meta->tables [MONO_TABLE_MODULEREF].rows);
797                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
798                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
799
800                         /* 2 bits used to encode tag (ECMA spec claims 3) */
801                         field_size = rtsize (n, 16 - 2);
802                         break;
803                 }
804
805                 /*
806                  * encode field size as follows (we just need to
807                  * distinguish them).
808                  *
809                  * 4 -> 3
810                  * 2 -> 1
811                  * 1 -> 0
812                  */
813                 bitfield |= (field_size-1) << shift;
814                 shift += 2;
815                 size += field_size;
816                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
817         }
818
819         *result_bitfield = (i << 24) | bitfield;
820         return size;
821 }
822
823 /**
824  * mono_metadata_compute_table_bases:
825  * @meta: metadata context to compute table values
826  *
827  * Computes the table bases for the metadata structure.
828  * This is an internal function used by the image loader code.
829  */
830 void
831 mono_metadata_compute_table_bases (MonoImage *meta)
832 {
833         int i;
834         const char *base = meta->tables_base;
835         
836         for (i = 0; i < MONO_TABLE_NUM; i++) {
837                 MonoTableInfo *table = &meta->tables [i];
838                 if (table->rows == 0)
839                         continue;
840
841                 table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
842                 table->base = base;
843                 base += table->rows * table->row_size;
844         }
845 }
846
847 /**
848  * mono_metadata_locate:
849  * @meta: metadata context
850  * @table: table code.
851  * @idx: index of element to retrieve from @table.
852  *
853  * Returns: a pointer to the @idx element in the metadata table
854  * whose code is @table.
855  */
856 const char *
857 mono_metadata_locate (MonoImage *meta, int table, int idx)
858 {
859         /* idx == 0 refers always to NULL */
860         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
861            
862         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
863 }
864
865 /**
866  * mono_metadata_locate_token:
867  * @meta: metadata context
868  * @token: metadata token
869  *
870  * Returns: a pointer to the data in the metadata represented by the
871  * token #token.
872  */
873 const char *
874 mono_metadata_locate_token (MonoImage *meta, guint32 token)
875 {
876         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
877 }
878
879 /**
880  * mono_metadata_string_heap:
881  * @meta: metadata context
882  * @index: index into the string heap.
883  *
884  * Returns: an in-memory pointer to the @index in the string heap.
885  */
886 const char *
887 mono_metadata_string_heap (MonoImage *meta, guint32 index)
888 {
889         g_return_val_if_fail (index < meta->heap_strings.size, "");
890         return meta->heap_strings.data + index;
891 }
892
893 /**
894  * mono_metadata_user_string:
895  * @meta: metadata context
896  * @index: index into the user string heap.
897  *
898  * Returns: an in-memory pointer to the @index in the user string heap ("#US").
899  */
900 const char *
901 mono_metadata_user_string (MonoImage *meta, guint32 index)
902 {
903         g_return_val_if_fail (index < meta->heap_us.size, "");
904         return meta->heap_us.data + index;
905 }
906
907 /**
908  * mono_metadata_blob_heap:
909  * @meta: metadata context
910  * @index: index into the blob.
911  *
912  * Returns: an in-memory pointer to the @index in the Blob heap.
913  */
914 const char *
915 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
916 {
917         g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
918         return meta->heap_blob.data + index;
919 }
920
921 /**
922  * mono_metadata_guid_heap:
923  * @meta: metadata context
924  * @index: index into the guid heap.
925  *
926  * Returns: an in-memory pointer to the @index in the guid heap.
927  */
928 const char *
929 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
930 {
931         --index;
932         index *= 16; /* adjust for guid size and 1-based index */
933         g_return_val_if_fail (index < meta->heap_guid.size, "");
934         return meta->heap_guid.data + index;
935 }
936
937 static const unsigned char *
938 dword_align (const unsigned char *ptr)
939 {
940 #if SIZEOF_VOID_P == 8
941         return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
942 #else
943         return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
944 #endif
945 }
946
947 /**
948  * mono_metadata_decode_row:
949  * @t: table to extract information from.
950  * @idx: index in table.
951  * @res: array of @res_size cols to store the results in
952  *
953  * This decompresses the metadata element @idx in table @t
954  * into the guint32 @res array that has res_size elements
955  */
956 void
957 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
958 {
959         guint32 bitfield = t->size_bitfield;
960         int i, count = mono_metadata_table_count (bitfield);
961         const char *data;
962
963         g_assert (idx < t->rows);
964         g_assert (idx >= 0);
965         data = t->base + idx * t->row_size;
966         
967         g_assert (res_size == count);
968
969         for (i = 0; i < count; i++) {
970                 int n = mono_metadata_table_size (bitfield, i);
971
972                 switch (n){
973                 case 1:
974                         res [i] = *data; break;
975                 case 2:
976                         res [i] = read16 (data); break;
977                 case 4:
978                         res [i] = read32 (data); break;
979                 default:
980                         g_assert_not_reached ();
981                 }
982                 data += n;
983         }
984 }
985
986 /**
987  * mono_metadata_decode_row_col:
988  * @t: table to extract information from.
989  * @idx: index for row in table.
990  * @col: column in the row.
991  *
992  * This function returns the value of column @col from the @idx
993  * row in the table @t.
994  */
995 guint32
996 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
997 {
998         guint32 bitfield = t->size_bitfield;
999         int i;
1000         register const char *data; 
1001         register int n;
1002         
1003         g_assert (idx < t->rows);
1004         g_assert (col < mono_metadata_table_count (bitfield));
1005         data = t->base + idx * t->row_size;
1006
1007         n = mono_metadata_table_size (bitfield, 0);
1008         for (i = 0; i < col; ++i) {
1009                 data += n;
1010                 n = mono_metadata_table_size (bitfield, i + 1);
1011         }
1012         switch (n) {
1013         case 1:
1014                 return *data;
1015         case 2:
1016                 return read16 (data);
1017         case 4:
1018                 return read32 (data);
1019         default:
1020                 g_assert_not_reached ();
1021         }
1022         return 0;
1023 }
1024
1025 /**
1026  * mono_metadata_decode_blob_size:
1027  * @ptr: pointer to a blob object
1028  * @rptr: the new position of the pointer
1029  *
1030  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1031  *
1032  * Returns: the size of the blob object
1033  */
1034 guint32
1035 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
1036 {
1037         const unsigned char *ptr = (const unsigned char *)xptr;
1038         guint32 size;
1039         
1040         if ((*ptr & 0x80) == 0){
1041                 size = ptr [0] & 0x7f;
1042                 ptr++;
1043         } else if ((*ptr & 0x40) == 0){
1044                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
1045                 ptr += 2;
1046         } else {
1047                 size = ((ptr [0] & 0x1f) << 24) +
1048                         (ptr [1] << 16) +
1049                         (ptr [2] << 8) +
1050                         ptr [3];
1051                 ptr += 4;
1052         }
1053         if (rptr)
1054                 *rptr = (char*)ptr;
1055         return size;
1056 }
1057
1058 /**
1059  * mono_metadata_decode_value:
1060  * @ptr: pointer to decode from
1061  * @rptr: the new position of the pointer
1062  *
1063  * This routine decompresses 32-bit values as specified in the "Blob and
1064  * Signature" section (22.2)
1065  *
1066  * Returns: the decoded value
1067  */
1068 guint32
1069 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1070 {
1071         const unsigned char *ptr = (const unsigned char *) _ptr;
1072         unsigned char b = *ptr;
1073         guint32 len;
1074         
1075         if ((b & 0x80) == 0){
1076                 len = b;
1077                 ++ptr;
1078         } else if ((b & 0x40) == 0){
1079                 len = ((b & 0x3f) << 8 | ptr [1]);
1080                 ptr += 2;
1081         } else {
1082                 len = ((b & 0x1f) << 24) |
1083                         (ptr [1] << 16) |
1084                         (ptr [2] << 8) |
1085                         ptr [3];
1086                 ptr += 4;
1087         }
1088         if (rptr)
1089                 *rptr = (char*)ptr;
1090         
1091         return len;
1092 }
1093
1094 /**
1095  * mono_metadata_decode_signed_value:
1096  * @ptr: pointer to decode from
1097  * @rptr: the new position of the pointer
1098  *
1099  * This routine decompresses 32-bit signed values
1100  * (not specified in the spec)
1101  *
1102  * Returns: the decoded value
1103  */
1104 gint32
1105 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1106 {
1107         guint32 uval = mono_metadata_decode_value (ptr, rptr);
1108         gint32 ival = uval >> 1;
1109         if (!(uval & 1))
1110                 return ival;
1111         /* ival is a truncated 2's complement negative number.  */
1112         if (ival < 0x40)
1113                 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1114                 return ival - 0x40;
1115         if (ival < 0x2000)
1116                 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1117                 return ival - 0x2000;
1118         if (ival < 0x10000000)
1119                 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1120                 return ival - 0x10000000;
1121         g_assert (ival < 0x20000000);
1122         g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1123         return ival - 0x20000000;
1124 }
1125
1126 /* 
1127  * Translates the given 1-based index into the Method, Field, Event, or Param tables
1128  * using the *Ptr tables in uncompressed metadata, if they are available.
1129  *
1130  * FIXME: The caller is not forced to call this function, which is error-prone, since 
1131  * forgetting to call it would only show up as a bug on uncompressed metadata.
1132  */
1133 guint32
1134 mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
1135 {
1136         if (!image->uncompressed_metadata)
1137                 return idx;
1138
1139         switch (table) {
1140         case MONO_TABLE_METHOD:
1141                 if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
1142                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
1143                 else
1144                         return idx;
1145         case MONO_TABLE_FIELD:
1146                 if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
1147                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
1148                 else
1149                         return idx;
1150         case MONO_TABLE_EVENT:
1151                 if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
1152                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
1153                 else
1154                         return idx;
1155         case MONO_TABLE_PROPERTY:
1156                 if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
1157                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
1158                 else
1159                         return idx;
1160         case MONO_TABLE_PARAM:
1161                 if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
1162                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
1163                 else
1164                         return idx;
1165         default:
1166                 return idx;
1167         }
1168 }
1169
1170 /**
1171  * mono_metadata_decode_table_row:
1172  *
1173  *   Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1174  * uncompressed metadata into account, so it should be used to access the
1175  * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1176  * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1177  */
1178 void
1179 mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
1180 {
1181         if (image->uncompressed_metadata)
1182                 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1183
1184         mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
1185 }
1186
1187 /**
1188  * mono_metadata_decode_table_row_col:
1189  *
1190  *   Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1191  * uncompressed metadata into account, so it should be used to access the
1192  * Method, Field, Param and Event tables.
1193  */
1194 guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
1195 {
1196         if (image->uncompressed_metadata)
1197                 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1198
1199         return mono_metadata_decode_row_col (&image->tables [table], idx, col);
1200 }
1201
1202 /*
1203  * mono_metadata_parse_typedef_or_ref:
1204  * @m: a metadata context.
1205  * @ptr: a pointer to an encoded TypedefOrRef in @m
1206  * @rptr: pointer updated to match the end of the decoded stream
1207  *
1208  * Returns: a token valid in the @m metadata decoded from
1209  * the compressed representation.
1210  */
1211 guint32
1212 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1213 {
1214         guint32 token;
1215         token = mono_metadata_decode_value (ptr, &ptr);
1216         if (rptr)
1217                 *rptr = ptr;
1218         return mono_metadata_token_from_dor (token);
1219 }
1220
1221 /*
1222  * mono_metadata_parse_custom_mod:
1223  * @m: a metadata context.
1224  * @dest: storage where the info about the custom modifier is stored (may be NULL)
1225  * @ptr: a pointer to (possibly) the start of a custom modifier list
1226  * @rptr: pointer updated to match the end of the decoded stream
1227  *
1228  * Checks if @ptr points to a type custom modifier compressed representation.
1229  *
1230  * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1231  */
1232 int
1233 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1234 {
1235         MonoCustomMod local;
1236         if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1237                 if (!dest)
1238                         dest = &local;
1239                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1240                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1241                 return TRUE;
1242         }
1243         return FALSE;
1244 }
1245
1246 /*
1247  * mono_metadata_parse_array_internal:
1248  * @m: a metadata context.
1249  * @transient: whenever to allocate data from the heap
1250  * @ptr: a pointer to an encoded array description.
1251  * @rptr: pointer updated to match the end of the decoded stream
1252  *
1253  * Decodes the compressed array description found in the metadata @m at @ptr.
1254  *
1255  * Returns: a #MonoArrayType structure describing the array type
1256  * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1257  * on the value of @transient.
1258  *
1259  * LOCKING: Acquires the loader lock
1260  */
1261 static MonoArrayType *
1262 mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
1263                                                                         gboolean transient, const char *ptr, const char **rptr)
1264 {
1265         int i;
1266         MonoArrayType *array;
1267         MonoType *etype;
1268         
1269         array = transient ? g_malloc0 (sizeof (MonoArrayType)) : mono_image_alloc0 (m, sizeof (MonoArrayType));
1270         etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
1271         if (!etype)
1272                 return NULL;
1273         array->eklass = mono_class_from_mono_type (etype);
1274         array->rank = mono_metadata_decode_value (ptr, &ptr);
1275
1276         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1277         if (array->numsizes)
1278                 array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : mono_image_alloc0 (m, sizeof (int) * array->numsizes);
1279         for (i = 0; i < array->numsizes; ++i)
1280                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1281
1282         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1283         if (array->numlobounds)
1284                 array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
1285         for (i = 0; i < array->numlobounds; ++i)
1286                 array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1287
1288         if (rptr)
1289                 *rptr = ptr;
1290         return array;
1291 }
1292
1293 MonoArrayType *
1294 mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
1295                                                                 const char *ptr, const char **rptr)
1296 {
1297         return mono_metadata_parse_array_internal (m, container, FALSE, ptr, rptr);
1298 }
1299
1300 MonoArrayType *
1301 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1302 {
1303         return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
1304 }
1305
1306 /*
1307  * mono_metadata_free_array:
1308  * @array: array description
1309  *
1310  * Frees the array description returned from mono_metadata_parse_array().
1311  */
1312 void
1313 mono_metadata_free_array (MonoArrayType *array)
1314 {
1315         g_free (array->sizes);
1316         g_free (array->lobounds);
1317         g_free (array);
1318 }
1319
1320 /*
1321  * need to add common field and param attributes combinations:
1322  * [out] param
1323  * public static
1324  * public static literal
1325  * private
1326  * private static
1327  * private static literal
1328  */
1329 static const MonoType
1330 builtin_types[] = {
1331         /* data, attrs, type,              nmods, byref, pinned */
1332         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
1333         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
1334         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
1335         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
1336         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
1337         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
1338         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
1339         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
1340         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
1341         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
1342         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1343         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1344         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1345         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1346         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1347         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1348         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1349         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1350         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1351         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1352         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1353         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1354         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1355         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1356         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1357         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1358         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1359         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1360         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0},
1361         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1362         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1363         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1364         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1365         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1366 };
1367
1368 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1369
1370 static GHashTable *type_cache = NULL;
1371 static int next_generic_inst_id = 0;
1372
1373 static MonoImageSet *mscorlib_image_set;
1374 static GPtrArray *image_sets;
1375
1376 static guint mono_generic_class_hash (gconstpointer data);
1377
1378 /*
1379  * MonoTypes with modifies are never cached, so we never check or use that field.
1380  */
1381 static guint
1382 mono_type_hash (gconstpointer data)
1383 {
1384         const MonoType *type = (const MonoType *) data;
1385         if (type->type == MONO_TYPE_GENERICINST)
1386                 return mono_generic_class_hash (type->data.generic_class);
1387         else
1388                 return type->type | (type->byref << 8) | (type->attrs << 9);
1389 }
1390
1391 static gint
1392 mono_type_equal (gconstpointer ka, gconstpointer kb)
1393 {
1394         const MonoType *a = (const MonoType *) ka;
1395         const MonoType *b = (const MonoType *) kb;
1396         
1397         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1398                 return 0;
1399         /* need other checks */
1400         return 1;
1401 }
1402
1403 guint
1404 mono_metadata_generic_inst_hash (gconstpointer data)
1405 {
1406         const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1407         guint hash = 0;
1408         int i;
1409         
1410         for (i = 0; i < ginst->type_argc; ++i) {
1411                 hash *= 13;
1412                 hash += mono_metadata_type_hash (ginst->type_argv [i]);
1413         }
1414
1415         return hash ^ (ginst->is_open << 8);
1416 }
1417
1418 static gboolean
1419 mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
1420 {
1421         int i;
1422
1423 #ifndef MONO_SMALL_CONFIG
1424         if (a->id && b->id) {
1425                 if (a->id == b->id)
1426                         return TRUE;
1427                 if (!signature_only)
1428                         return FALSE;
1429         }
1430 #endif
1431
1432         if (a->is_open != b->is_open || a->type_argc != b->type_argc)
1433                 return FALSE;
1434         for (i = 0; i < a->type_argc; ++i) {
1435                 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
1436                         return FALSE;
1437         }
1438         return TRUE;
1439 }
1440
1441 gboolean
1442 mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1443 {
1444         const MonoGenericInst *a = (const MonoGenericInst *) ka;
1445         const MonoGenericInst *b = (const MonoGenericInst *) kb;
1446
1447         return mono_generic_inst_equal_full (a, b, FALSE);
1448 }
1449
1450 static guint
1451 mono_generic_class_hash (gconstpointer data)
1452 {
1453         const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1454         guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1455
1456         hash *= 13;
1457         hash += gclass->is_tb_open;
1458         hash += mono_metadata_generic_context_hash (&gclass->context);
1459
1460         return hash;
1461 }
1462
1463 static gboolean
1464 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1465 {
1466         const MonoGenericClass *a = (const MonoGenericClass *) ka;
1467         const MonoGenericClass *b = (const MonoGenericClass *) kb;
1468
1469         return _mono_metadata_generic_class_equal (a, b, FALSE);
1470 }
1471
1472 /**
1473  * mono_metadata_init:
1474  *
1475  * Initialize the global variables of this module.
1476  * This is a Mono runtime internal function.
1477  */
1478 void
1479 mono_metadata_init (void)
1480 {
1481         int i;
1482
1483         type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1484
1485         for (i = 0; i < NBUILTIN_TYPES (); ++i)
1486                 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1487 }
1488
1489 /**
1490  * mono_metadata_cleanup:
1491  *
1492  * Free all resources used by this module.
1493  * This is a Mono runtime internal function.
1494  */
1495 void
1496 mono_metadata_cleanup (void)
1497 {
1498         g_hash_table_destroy (type_cache);
1499         type_cache = NULL;
1500         g_ptr_array_free (image_sets, TRUE);
1501         image_sets = NULL;
1502 }
1503
1504 /**
1505  * mono_metadata_parse_type:
1506  * @m: metadata context
1507  * @mode: king of type that may be found at @ptr
1508  * @opt_attrs: optional attributes to store in the returned type
1509  * @ptr: pointer to the type representation
1510  * @rptr: pointer updated to match the end of the decoded stream
1511  * @transient: whenever to allocate the result from the heap or from a mempool
1512  * 
1513  * Decode a compressed type description found at @ptr in @m.
1514  * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1515  * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1516  * This function can be used to decode type descriptions in method signatures,
1517  * field signatures, locals signatures etc.
1518  *
1519  * To parse a generic type, `generic_container' points to the current class'es
1520  * (the `generic_container' field in the MonoClass) or the current generic method's
1521  * (stored in image->property_hash) generic container.
1522  * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1523  * this MonoGenericContainer.
1524  *
1525  * LOCKING: Acquires the loader lock.
1526  *
1527  * Returns: a #MonoType structure representing the decoded type.
1528  */
1529 static MonoType*
1530 mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
1531                                                                    short opt_attrs, gboolean transient, const char *ptr, const char **rptr)
1532 {
1533         MonoType *type, *cached;
1534         MonoType stype;
1535         gboolean byref = FALSE;
1536         gboolean pinned = FALSE;
1537         const char *tmp_ptr;
1538         int count = 0;
1539         gboolean found;
1540
1541         /*
1542          * According to the spec, custom modifiers should come before the byref
1543          * flag, but the IL produced by ilasm from the following signature:
1544          *   object modopt(...) &
1545          * starts with a byref flag, followed by the modifiers. (bug #49802)
1546          * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1547          * it would be better to treat byref as real type constructor instead of
1548          * a modifier...
1549          * Also, pinned should come before anything else, but some MSV++ produced
1550          * assemblies violate this (#bug 61990).
1551          */
1552
1553         /* Count the modifiers first */
1554         tmp_ptr = ptr;
1555         found = TRUE;
1556         while (found) {
1557                 switch (*tmp_ptr) {
1558                 case MONO_TYPE_PINNED:
1559                 case MONO_TYPE_BYREF:
1560                         ++tmp_ptr;
1561                         break;
1562                 case MONO_TYPE_CMOD_REQD:
1563                 case MONO_TYPE_CMOD_OPT:
1564                         count ++;
1565                         mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1566                         break;
1567                 default:
1568                         found = FALSE;
1569                 }
1570         }
1571
1572         if (count) {
1573                 int size;
1574
1575                 size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
1576                 type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size);
1577                 type->num_mods = count;
1578                 if (count > 64)
1579                         g_warning ("got more than 64 modifiers in type");
1580         } else {
1581                 type = &stype;
1582                 memset (type, 0, MONO_SIZEOF_TYPE);
1583         }
1584
1585         /* Parse pinned, byref and custom modifiers */
1586         found = TRUE;
1587         count = 0;
1588         while (found) {
1589                 switch (*ptr) {
1590                 case MONO_TYPE_PINNED:
1591                         pinned = TRUE;
1592                         ++ptr;
1593                         break;
1594                 case MONO_TYPE_BYREF:
1595                         byref = TRUE;
1596                         ++ptr;
1597                         break;
1598                 case MONO_TYPE_CMOD_REQD:
1599                 case MONO_TYPE_CMOD_OPT:
1600                         mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1601                         count ++;
1602                         break;
1603                 default:
1604                         found = FALSE;
1605                 }
1606         }
1607         
1608         type->attrs = opt_attrs;
1609         type->byref = byref;
1610         type->pinned = pinned ? 1 : 0;
1611
1612         if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) {
1613                 return NULL;
1614         }
1615
1616         if (rptr)
1617                 *rptr = ptr;
1618
1619         if (!type->num_mods && !transient) {
1620                 /* no need to free type here, because it is on the stack */
1621                 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1622                         MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1623
1624                         /* Consider the case:
1625
1626                              class Foo<T> { class Bar {} }
1627                              class Test : Foo<Test>.Bar {}
1628
1629                            When Foo<Test> is being expanded, 'Test' isn't yet initialized.  It's actually in
1630                            a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1631
1632                            We ensure that the MonoClass is in a state that we can canonicalize to:
1633
1634                              klass->byval_arg.data.klass == klass
1635                              klass->this_arg.data.klass == klass
1636
1637                            If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1638
1639                            LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1640                                     of a MonoClass which currently holds the loader lock.  'type' is local.
1641                         */
1642                         if (ret->data.klass == type->data.klass) {
1643                                 return ret;
1644                         }
1645                 }
1646                 /* No need to use locking since nobody is modifying the hash table */
1647                 if ((cached = g_hash_table_lookup (type_cache, type))) {
1648                         return cached;
1649                 }
1650         }
1651         
1652         /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1653         
1654         if (type == &stype) {
1655                 type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE);
1656                 memcpy (type, &stype, MONO_SIZEOF_TYPE);
1657         }
1658         return type;
1659 }
1660
1661 MonoType*
1662 mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
1663                                                            short opt_attrs, const char *ptr, const char **rptr)
1664 {
1665         return mono_metadata_parse_type_internal (m, container, mode, opt_attrs, FALSE, ptr, rptr);
1666 }
1667
1668 /*
1669  * LOCKING: Acquires the loader lock.
1670  */
1671 MonoType*
1672 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1673                           const char *ptr, const char **rptr)
1674 {
1675         return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
1676 }
1677
1678 gboolean
1679 mono_metadata_method_has_param_attrs (MonoImage *m, int def)
1680 {
1681         MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1682         MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1683         guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1684
1685         if (def < methodt->rows)
1686                 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1687         else
1688                 lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
1689
1690         for (i = param_index; i < lastp; ++i) {
1691                 guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
1692                 if (flags)
1693                         return TRUE;
1694         }
1695
1696         return FALSE;
1697 }
1698
1699 /*
1700  * mono_metadata_get_param_attrs:
1701  *
1702  * @m The image to loader parameter attributes from
1703  * @def method def token (one based)
1704  * @param_count number of params to decode including the return value
1705  *
1706  *   Return the parameter attributes for the method whose MethodDef index is DEF. The 
1707  * returned memory needs to be freed by the caller. If all the param attributes are
1708  * 0, then NULL is returned.
1709  */
1710 int*
1711 mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
1712 {
1713         MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1714         MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1715         guint32 cols [MONO_PARAM_SIZE];
1716         guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1717         int *pattrs = NULL;
1718
1719         if (def < methodt->rows)
1720                 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1721         else
1722                 lastp = paramt->rows + 1;
1723
1724         for (i = param_index; i < lastp; ++i) {
1725                 mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1726                 if (cols [MONO_PARAM_FLAGS]) {
1727                         if (!pattrs)
1728                                 pattrs = g_new0 (int, param_count);
1729                         /* at runtime we just ignore this kind of malformed file:
1730                         * the verifier can signal the error to the user
1731                         */
1732                         if (cols [MONO_PARAM_SEQUENCE] >= param_count)
1733                                 continue;
1734                         pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1735                 }
1736         }
1737
1738         return pattrs;
1739 }
1740
1741 /*
1742  * mono_metadata_parse_signature_full:
1743  * @image: metadata context
1744  * @generic_container: generic container
1745  * @toke: metadata token
1746  *
1747  * Decode a method signature stored in the STANDALONESIG table
1748  *
1749  * LOCKING: Assumes the loader lock is held.
1750  *
1751  * Returns: a MonoMethodSignature describing the signature.
1752  */
1753 MonoMethodSignature*
1754 mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
1755 {
1756         MonoTableInfo *tables = image->tables;
1757         guint32 idx = mono_metadata_token_index (token);
1758         guint32 sig;
1759         const char *ptr;
1760
1761         if (image->dynamic)
1762                 return mono_lookup_dynamic_token (image, token, NULL);
1763
1764         g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1765                 
1766         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1767
1768         ptr = mono_metadata_blob_heap (image, sig);
1769         mono_metadata_decode_blob_size (ptr, &ptr);
1770
1771         return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL); 
1772 }
1773
1774 /*
1775  * mono_metadata_parse_signature:
1776  * @image: metadata context
1777  * @toke: metadata token
1778  *
1779  * Decode a method signature stored in the STANDALONESIG table
1780  *
1781  * Returns: a MonoMethodSignature describing the signature.
1782  */
1783 MonoMethodSignature*
1784 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1785 {
1786         return mono_metadata_parse_signature_full (image, NULL, token);
1787 }
1788
1789 /*
1790  * mono_metadata_signature_alloc:
1791  * @image: metadata context
1792  * @nparmas: number of parameters in the signature
1793  *
1794  * Allocate a MonoMethodSignature structure with the specified number of params.
1795  * The return type and the params types need to be filled later.
1796  * This is a Mono runtime internal function.
1797  *
1798  * LOCKING: Assumes the loader lock is held.
1799  *
1800  * Returns: the new MonoMethodSignature structure.
1801  */
1802 MonoMethodSignature*
1803 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1804 {
1805         MonoMethodSignature *sig;
1806
1807         sig = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
1808         sig->param_count = nparams;
1809         sig->sentinelpos = -1;
1810
1811         return sig;
1812 }
1813
1814 static MonoMethodSignature*
1815 mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
1816 {
1817         int sigsize;
1818         MonoMethodSignature *ret;
1819         sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
1820
1821         if (image) {
1822                 ret = mono_image_alloc (image, sigsize);
1823         } else if (mp) {
1824                 ret = mono_mempool_alloc (mp, sigsize);
1825         } else {
1826                 ret = g_malloc (sigsize);
1827         }
1828         memcpy (ret, sig, sigsize);
1829         return ret;
1830 }
1831
1832 MonoMethodSignature*
1833 mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
1834 {
1835         return mono_metadata_signature_dup_internal (image, NULL, sig);
1836 }
1837
1838 /*The mempool is accessed without synchronization*/
1839 MonoMethodSignature*
1840 mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
1841 {
1842         return mono_metadata_signature_dup_internal (NULL, mp, sig);
1843 }
1844
1845 /*
1846  * mono_metadata_signature_dup:
1847  * @sig: method signature
1848  *
1849  * Duplicate an existing MonoMethodSignature so it can be modified.
1850  * This is a Mono runtime internal function.
1851  *
1852  * Returns: the new MonoMethodSignature structure.
1853  */
1854 MonoMethodSignature*
1855 mono_metadata_signature_dup (MonoMethodSignature *sig)
1856 {
1857         return mono_metadata_signature_dup_full (NULL, sig);
1858 }
1859
1860 /*
1861  * mono_metadata_signature_size:
1862  *
1863  *   Return the amount of memory allocated to SIG.
1864  */
1865 guint32
1866 mono_metadata_signature_size (MonoMethodSignature *sig)
1867 {
1868         return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
1869 }
1870
1871 /*
1872  * mono_metadata_parse_method_signature:
1873  * @m: metadata context
1874  * @generic_container: generics container
1875  * @def: the MethodDef index or 0 for Ref signatures.
1876  * @ptr: pointer to the signature metadata representation
1877  * @rptr: pointer updated to match the end of the decoded stream
1878  *
1879  * Decode a method signature stored at @ptr.
1880  * This is a Mono runtime internal function.
1881  *
1882  * LOCKING: Assumes the loader lock is held.
1883  *
1884  * Returns: a MonoMethodSignature describing the signature.
1885  */
1886 MonoMethodSignature *
1887 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
1888                                            int def, const char *ptr, const char **rptr)
1889 {
1890         MonoMethodSignature *method;
1891         int i, *pattrs = NULL;
1892         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1893         guint32 gen_param_count = 0;
1894         gboolean is_open = FALSE;
1895
1896         if (*ptr & 0x10)
1897                 gen_param_count = 1;
1898         if (*ptr & 0x20)
1899                 hasthis = 1;
1900         if (*ptr & 0x40)
1901                 explicit_this = 1;
1902         call_convention = *ptr & 0x0F;
1903         ptr++;
1904         if (gen_param_count)
1905                 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
1906         param_count = mono_metadata_decode_value (ptr, &ptr);
1907
1908         if (def)
1909                 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 */
1910
1911         method = mono_metadata_signature_alloc (m, param_count);
1912         method->hasthis = hasthis;
1913         method->explicit_this = explicit_this;
1914         method->call_convention = call_convention;
1915         method->generic_param_count = gen_param_count;
1916
1917         if (call_convention != 0xa) {
1918                 method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr);
1919                 if (!method->ret) {
1920                         mono_metadata_free_method_signature (method);
1921                         g_free (pattrs);
1922                         return NULL;
1923                 }
1924                 is_open = mono_class_is_open_constructed_type (method->ret);
1925         }
1926
1927         for (i = 0; i < method->param_count; ++i) {
1928                 if (*ptr == MONO_TYPE_SENTINEL) {
1929                         if (method->call_convention != MONO_CALL_VARARG || def) {
1930                                 g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
1931                                 g_free (pattrs);
1932                                 return NULL;
1933                         }
1934                         if (method->sentinelpos >= 0) {
1935                                 g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
1936                                 g_free (pattrs);
1937                                 return NULL;
1938                         }
1939                         method->sentinelpos = i;
1940                         ptr++;
1941                 }
1942                 method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
1943                 if (!method->params [i]) {
1944                         mono_metadata_free_method_signature (method);
1945                         g_free (pattrs);
1946                         return NULL;
1947                 }
1948                 if (!is_open)
1949                         is_open = mono_class_is_open_constructed_type (method->params [i]);
1950         }
1951
1952         /* The sentinel could be missing if the caller does not pass any additional arguments */
1953         if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
1954                 method->sentinelpos = method->param_count;
1955
1956         method->has_type_parameters = is_open;
1957
1958         if (def && (method->call_convention == MONO_CALL_VARARG))
1959                 method->sentinelpos = method->param_count;
1960
1961         g_free (pattrs);
1962
1963         if (rptr)
1964                 *rptr = ptr;
1965         /*
1966          * Add signature to a cache and increase ref count...
1967          */
1968
1969         return method;
1970 }
1971
1972 /*
1973  * mono_metadata_parse_method_signature:
1974  * @m: metadata context
1975  * @def: the MethodDef index or 0 for Ref signatures.
1976  * @ptr: pointer to the signature metadata representation
1977  * @rptr: pointer updated to match the end of the decoded stream
1978  *
1979  * Decode a method signature stored at @ptr.
1980  * This is a Mono runtime internal function.
1981  *
1982  * LOCKING: Assumes the loader lock is held.
1983  *
1984  * Returns: a MonoMethodSignature describing the signature.
1985  */
1986 MonoMethodSignature *
1987 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
1988 {
1989         return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
1990 }
1991
1992 /*
1993  * mono_metadata_free_method_signature:
1994  * @sig: signature to destroy
1995  *
1996  * Free the memory allocated in the signature @sig.
1997  * This method needs to be robust and work also on partially-built
1998  * signatures, so it does extra checks.
1999  */
2000 void
2001 mono_metadata_free_method_signature (MonoMethodSignature *sig)
2002 {
2003         /* Everything is allocated from mempools */
2004         /*
2005         int i;
2006         if (sig->ret)
2007                 mono_metadata_free_type (sig->ret);
2008         for (i = 0; i < sig->param_count; ++i) {
2009                 if (sig->params [i])
2010                         mono_metadata_free_type (sig->params [i]);
2011         }
2012         */
2013 }
2014
2015 void
2016 mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
2017 {
2018         int i;
2019
2020         /* Allocated in inflate_generic_signature () */
2021         if (sig->ret)
2022                 mono_metadata_free_type (sig->ret);
2023         for (i = 0; i < sig->param_count; ++i) {
2024                 if (sig->params [i])
2025                         mono_metadata_free_type (sig->params [i]);
2026         }
2027         g_free (sig);
2028 }
2029
2030 static gboolean
2031 inflated_method_equal (gconstpointer a, gconstpointer b)
2032 {
2033         const MonoMethodInflated *ma = a;
2034         const MonoMethodInflated *mb = b;
2035         if (ma->declaring != mb->declaring)
2036                 return FALSE;
2037         if (ma->method.method.is_mb_open != mb->method.method.is_mb_open)
2038                 return FALSE;
2039         return mono_metadata_generic_context_equal (&ma->context, &mb->context);
2040 }
2041
2042 static guint
2043 inflated_method_hash (gconstpointer a)
2044 {
2045         const MonoMethodInflated *ma = a;
2046         return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)) + ma->method.method.is_mb_open;
2047 }
2048
2049 static gboolean
2050 inflated_signature_equal (gconstpointer a, gconstpointer b)
2051 {
2052         const MonoInflatedMethodSignature *sig1 = a;
2053         const MonoInflatedMethodSignature *sig2 = b;
2054
2055         /* sig->sig is assumed to be canonized */
2056         if (sig1->sig != sig2->sig)
2057                 return FALSE;
2058         /* The generic instances are canonized */
2059         return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
2060 }
2061
2062 static guint
2063 inflated_signature_hash (gconstpointer a)
2064 {
2065         const MonoInflatedMethodSignature *sig = a;
2066
2067         /* sig->sig is assumed to be canonized */
2068         return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
2069 }
2070
2071 /*static void
2072 dump_ginst (MonoGenericInst *ginst)
2073 {
2074         int i;
2075         char *name;
2076
2077         g_print ("Ginst: <");
2078         for (i = 0; i < ginst->type_argc; ++i) {
2079                 if (i != 0)
2080                         g_print (", ");
2081                 name = mono_type_get_name (ginst->type_argv [i]);
2082                 g_print ("%s", name);
2083                 g_free (name);
2084         }
2085         g_print (">");
2086 }*/
2087
2088 static gboolean type_in_image (MonoType *type, MonoImage *image);
2089
2090 static gboolean
2091 signature_in_image (MonoMethodSignature *sig, MonoImage *image)
2092 {
2093         gpointer iter = NULL;
2094         MonoType *p;
2095
2096         while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2097                 if (type_in_image (p, image))
2098                         return TRUE;
2099
2100         return type_in_image (mono_signature_get_return_type (sig), image);
2101 }
2102
2103 static gboolean
2104 ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
2105 {
2106         int i;
2107
2108         for (i = 0; i < ginst->type_argc; ++i) {
2109                 if (type_in_image (ginst->type_argv [i], image))
2110                         return TRUE;
2111         }
2112
2113         return FALSE;
2114 }
2115
2116 static gboolean
2117 gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
2118 {
2119         return gclass->container_class->image == image ||
2120                 ginst_in_image (gclass->context.class_inst, image);
2121 }
2122
2123 static gboolean
2124 type_in_image (MonoType *type, MonoImage *image)
2125 {
2126 retry:
2127         switch (type->type) {
2128         case MONO_TYPE_GENERICINST:
2129                 return gclass_in_image (type->data.generic_class, image);
2130         case MONO_TYPE_PTR:
2131                 type = type->data.type;
2132                 goto retry;
2133         case MONO_TYPE_SZARRAY:
2134                 type = &type->data.klass->byval_arg;
2135                 goto retry;
2136         case MONO_TYPE_ARRAY:
2137                 type = &type->data.array->eklass->byval_arg;
2138                 goto retry;
2139         case MONO_TYPE_FNPTR:
2140                 return signature_in_image (type->data.method, image);
2141         case MONO_TYPE_VAR: {
2142                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2143                 if (container) {
2144                         g_assert (!container->is_method);
2145                         /*
2146                          * FIXME: The following check is here solely
2147                          * for monodis, which uses the internal
2148                          * function
2149                          * mono_metadata_load_generic_params().  The
2150                          * caller of that function needs to fill in
2151                          * owner->klass or owner->method of the
2152                          * returned struct, but monodis doesn't do
2153                          * that.  The image unloading depends on that,
2154                          * however, so a crash results without this
2155                          * check.
2156                          */
2157                         if (!container->owner.klass)
2158                                 return container->image == image;
2159                         return container->owner.klass->image == image;
2160                 } else {
2161                         return type->data.generic_param->image == image;
2162                 }
2163         }
2164         case MONO_TYPE_MVAR: {
2165                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2166                 if (type->data.generic_param->image == image)
2167                         return TRUE;
2168                 if (container) {
2169                         g_assert (container->is_method);
2170                         if (!container->owner.method)
2171                                 /* RefEmit created generic param whose method is not finished */
2172                                 return container->image == image;
2173                         return container->owner.method->klass->image == image;
2174                 } else {
2175                         return type->data.generic_param->image == image;
2176                 }
2177         }
2178         default:
2179                 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2180                 return image == mono_class_from_mono_type (type)->image;
2181         }
2182 }
2183
2184 /*
2185  * get_image_set:
2186  *
2187  *   Return a MonoImageSet representing the set of images in IMAGES.
2188  * 
2189  * LOCKING: Assumes the loader lock is held.
2190  */
2191 static MonoImageSet*
2192 get_image_set (MonoImage **images, int nimages)
2193 {
2194         int i, j, k;
2195         MonoImageSet *set;
2196         GSList *l;
2197
2198         if (!image_sets)
2199                 image_sets = g_ptr_array_new ();
2200
2201         /* Common case */
2202         if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
2203                 return mscorlib_image_set;
2204
2205         /* Happens with empty generic instances */
2206         if (nimages == 0)
2207                 return mscorlib_image_set;
2208
2209         if (images [0] == mono_defaults.corlib && nimages > 1)
2210                 l = images [1]->image_sets;
2211         else
2212                 l = images [0]->image_sets;
2213
2214         set = NULL;
2215         for (; l; l = l->next) {
2216                 set = l->data;
2217
2218                 if (set->nimages == nimages) {
2219                         for (j = 0; j < nimages; ++j) {
2220                                 for (k = 0; k < nimages; ++k)
2221                                         if (set->images [k] == images [j])
2222                                                 break;
2223                                 if (k == nimages)
2224                                         /* Not found */
2225                                         break;
2226                         }
2227                         if (j == nimages)
2228                                 /* Found */
2229                                 break;
2230                 }
2231         }
2232
2233         if (!l) {
2234                 /* Not found */
2235                 set = g_new0 (MonoImageSet, 1);
2236                 set->nimages = nimages;
2237                 set->images = g_new0 (MonoImage*, nimages);
2238                 InitializeCriticalSection (&set->lock);
2239                 for (i = 0; i < nimages; ++i)
2240                         set->images [i] = images [i];
2241                 set->gclass_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
2242                 set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
2243                 set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
2244                 set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
2245         
2246                 for (i = 0; i < nimages; ++i)
2247                         set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
2248
2249                 g_ptr_array_add (image_sets, set);
2250         }
2251
2252         if (nimages == 1 && images [0] == mono_defaults.corlib)
2253                 mscorlib_image_set = set;
2254
2255         return set;
2256 }
2257
2258 static void
2259 delete_image_set (MonoImageSet *set)
2260 {
2261         int i;
2262
2263         g_hash_table_destroy (set->gclass_cache);
2264         g_hash_table_destroy (set->ginst_cache);
2265         g_hash_table_destroy (set->gmethod_cache);
2266         g_hash_table_destroy (set->gsignature_cache);
2267
2268         for (i = 0; i < set->nimages; ++i)
2269                 set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
2270
2271         g_ptr_array_remove (image_sets, set);
2272
2273         if (set->mempool)
2274                 mono_mempool_destroy (set->mempool);
2275         g_free (set->images);
2276         DeleteCriticalSection (&set->lock);
2277         g_free (set);
2278 }
2279
2280 static void
2281 mono_image_set_lock (MonoImageSet *set)
2282 {
2283         EnterCriticalSection (&set->lock);
2284 }
2285
2286 static void
2287 mono_image_set_unlock (MonoImageSet *set)
2288 {
2289         LeaveCriticalSection (&set->lock);
2290 }
2291
2292 gpointer
2293 mono_image_set_alloc (MonoImageSet *set, guint size)
2294 {
2295         gpointer res;
2296
2297         mono_image_set_lock (set);
2298         if (!set->mempool)
2299                 set->mempool = mono_mempool_new_size (1024);
2300         res = mono_mempool_alloc (set->mempool, size);
2301         mono_image_set_unlock (set);
2302
2303         return res;
2304 }
2305
2306 gpointer
2307 mono_image_set_alloc0 (MonoImageSet *set, guint size)
2308 {
2309         gpointer res;
2310
2311         mono_image_set_lock (set);
2312         if (!set->mempool)
2313                 set->mempool = mono_mempool_new_size (1024);
2314         res = mono_mempool_alloc0 (set->mempool, size);
2315         mono_image_set_unlock (set);
2316
2317         return res;
2318 }
2319
2320 char*
2321 mono_image_set_strdup (MonoImageSet *set, const char *s)
2322 {
2323         char *res;
2324
2325         mono_image_set_lock (set);
2326         if (!set->mempool)
2327                 set->mempool = mono_mempool_new_size (1024);
2328         res = mono_mempool_strdup (set->mempool, s);
2329         mono_image_set_unlock (set);
2330
2331         return res;
2332 }
2333
2334 /* 
2335  * Structure used by the collect_..._images functions to store the image list.
2336  */
2337 typedef struct {
2338         MonoImage *image_buf [64];
2339         MonoImage **images;
2340         int nimages, images_len;
2341 } CollectData;
2342
2343 static void
2344 collect_data_init (CollectData *data)
2345 {
2346         data->images = data->image_buf;
2347         data->images_len = 64;
2348         data->nimages = 0;
2349 }
2350
2351 static void
2352 collect_data_free (CollectData *data)
2353 {
2354         if (data->images != data->image_buf)
2355                 g_free (data->images);
2356 }
2357
2358 static void
2359 enlarge_data (CollectData *data)
2360 {
2361         int new_len = data->images_len < 16 ? 16 : data->images_len * 2;
2362         MonoImage **d = g_new (MonoImage *, new_len);
2363
2364         // FIXME: test this
2365         g_assert_not_reached ();
2366         memcpy (d, data->images, data->images_len);
2367         if (data->images != data->image_buf)
2368                 g_free (data->images);
2369         data->images = d;
2370         data->images_len = new_len;
2371 }
2372
2373 static inline void
2374 add_image (MonoImage *image, CollectData *data)
2375 {
2376         int i;
2377
2378         /* The arrays are small, so use a linear search instead of a hash table */
2379         for (i = 0; i < data->nimages; ++i)
2380                 if (data->images [i] == image)
2381                         return;
2382
2383         if (data->nimages == data->images_len)
2384                 enlarge_data (data);
2385
2386         data->images [data->nimages ++] = image;
2387 }
2388
2389 static void
2390 collect_type_images (MonoType *type, CollectData *data);
2391
2392 static void
2393 collect_ginst_images (MonoGenericInst *ginst, CollectData *data)
2394 {
2395         int i;
2396
2397         for (i = 0; i < ginst->type_argc; ++i) {
2398                 collect_type_images (ginst->type_argv [i], data);
2399         }
2400 }
2401
2402 static void
2403 collect_gclass_images (MonoGenericClass *gclass, CollectData *data)
2404 {
2405         add_image (gclass->container_class->image, data);
2406         if (gclass->context.class_inst)
2407                 collect_ginst_images (gclass->context.class_inst, data);
2408 }
2409
2410 static void
2411 collect_signature_images (MonoMethodSignature *sig, CollectData *data)
2412 {
2413         gpointer iter = NULL;
2414         MonoType *p;
2415
2416         collect_type_images (mono_signature_get_return_type (sig), data);
2417         while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2418                 collect_type_images (p, data);
2419 }
2420
2421 static void
2422 collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData *data)
2423 {
2424         collect_signature_images (sig->sig, data);
2425         if (sig->context.class_inst)
2426                 collect_ginst_images (sig->context.class_inst, data);
2427         if (sig->context.method_inst)
2428                 collect_ginst_images (sig->context.method_inst, data);
2429 }
2430
2431 static void
2432 collect_method_images (MonoMethodInflated *method, CollectData *data)
2433 {
2434         add_image (method->declaring->klass->image, data);
2435         if (method->context.class_inst)
2436                 collect_ginst_images (method->context.class_inst, data);
2437         if (method->context.method_inst)
2438                 collect_ginst_images (method->context.method_inst, data);
2439         /*
2440         if (((MonoMethod*)method)->signature)
2441                 collect_signature_images (mono_method_signature ((MonoMethod*)method), data);
2442         */
2443 }
2444
2445 static void
2446 collect_type_images (MonoType *type, CollectData *data)
2447 {
2448 retry:
2449         switch (type->type) {
2450         case MONO_TYPE_GENERICINST:
2451                 collect_gclass_images (type->data.generic_class, data);
2452                 break;
2453         case MONO_TYPE_PTR:
2454                 type = type->data.type;
2455                 goto retry;
2456         case MONO_TYPE_SZARRAY:
2457                 type = &type->data.klass->byval_arg;
2458                 goto retry;
2459         case MONO_TYPE_ARRAY:
2460                 type = &type->data.array->eklass->byval_arg;
2461                 goto retry;
2462         case MONO_TYPE_FNPTR:
2463                 //return signature_in_image (type->data.method, image);
2464                 g_assert_not_reached ();
2465         case MONO_TYPE_VAR: {
2466                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2467                 if (container) {
2468                         g_assert (!container->is_method);
2469                         /*
2470                          * FIXME: The following check is here solely
2471                          * for monodis, which uses the internal
2472                          * function
2473                          * mono_metadata_load_generic_params().  The
2474                          * caller of that function needs to fill in
2475                          * owner->klass or owner->method of the
2476                          * returned struct, but monodis doesn't do
2477                          * that.  The image unloading depends on that,
2478                          * however, so a crash results without this
2479                          * check.
2480                          */
2481                         if (!container->owner.klass)
2482                                 add_image (container->image, data);
2483                         else
2484                                 add_image (container->owner.klass->image, data);
2485                 } else {
2486                         add_image (type->data.generic_param->image, data);
2487                 }
2488         }
2489                 break;
2490         case MONO_TYPE_MVAR: {
2491                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2492                 if (type->data.generic_param->image)
2493                         add_image (type->data.generic_param->image, data);
2494                 if (container) {
2495                         if (!container->owner.method) {
2496                                 /* RefEmit created generic param whose method is not finished */
2497                                 add_image (container->image, data);
2498                         } else {
2499                                 g_assert (container->is_method);
2500                                 add_image (container->owner.method->klass->image, data);
2501                         }
2502                 } else {
2503                         add_image (type->data.generic_param->image, data);
2504                 }
2505         }
2506                 break;
2507         case MONO_TYPE_CLASS:
2508         case MONO_TYPE_VALUETYPE:
2509                 add_image (mono_class_from_mono_type (type)->image, data);
2510                 break;
2511         default:
2512                 add_image (mono_defaults.corlib, data);
2513         }
2514 }
2515
2516 typedef struct {
2517         MonoImage *image;
2518         GSList *list;
2519 } CleanForImageUserData;
2520
2521 static gboolean
2522 steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
2523 {
2524         MonoGenericClass *gclass = key;
2525         CleanForImageUserData *user_data = data;
2526
2527         g_assert (gclass_in_image (gclass, user_data->image));
2528
2529         user_data->list = g_slist_prepend (user_data->list, gclass);
2530         return TRUE;
2531 }
2532
2533 static gboolean
2534 steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
2535 {
2536         MonoGenericInst *ginst = key;
2537         CleanForImageUserData *user_data = data;
2538
2539         // This doesn't work during corlib compilation
2540         //g_assert (ginst_in_image (ginst, user_data->image));
2541
2542         user_data->list = g_slist_prepend (user_data->list, ginst);
2543         return TRUE;
2544 }
2545
2546 static gboolean
2547 inflated_method_in_image (gpointer key, gpointer value, gpointer data)
2548 {
2549         MonoImage *image = data;
2550         MonoMethodInflated *method = key;
2551
2552         // FIXME:
2553         // https://bugzilla.novell.com/show_bug.cgi?id=458168
2554         g_assert (method->declaring->klass->image == image ||
2555                 (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
2556                           (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image)));
2557
2558         return TRUE;
2559 }
2560
2561 static gboolean
2562 inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
2563 {
2564         MonoImage *image = data;
2565         MonoInflatedMethodSignature *sig = key;
2566
2567         return signature_in_image (sig->sig, image) ||
2568                 (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
2569                 (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
2570 }       
2571
2572 static void
2573 check_gmethod (gpointer key, gpointer value, gpointer data)
2574 {
2575         MonoMethodInflated *method = key;
2576         MonoImage *image = data;
2577
2578         if (method->context.class_inst)
2579                 g_assert (!ginst_in_image (method->context.class_inst, image));
2580         if (method->context.method_inst)
2581                 g_assert (!ginst_in_image (method->context.method_inst, image));
2582         if (((MonoMethod*)method)->signature)
2583                 g_assert (!signature_in_image (mono_method_signature ((MonoMethod*)method), image));
2584 }
2585
2586 /*
2587  * check_image_sets:
2588  *
2589  *   Run a consistency check on the image set data structures.
2590  */
2591 static G_GNUC_UNUSED void
2592 check_image_sets (MonoImage *image)
2593 {
2594         int i;
2595         GSList *l = image->image_sets;
2596
2597         if (!image_sets)
2598                 return;
2599
2600         for (i = 0; i < image_sets->len; ++i) {
2601                 MonoImageSet *set = g_ptr_array_index (image_sets, i);
2602
2603                 if (!g_slist_find (l, set)) {
2604                         g_hash_table_foreach (set->gmethod_cache, check_gmethod, image);
2605                 }
2606         }
2607 }
2608
2609 GSList*
2610 mono_metadata_clean_for_image (MonoImage *image)
2611 {
2612         CleanForImageUserData ginst_data, gclass_data;
2613         GSList *l, *set_list, *free_list = NULL;
2614
2615         //check_image_sets (image);
2616
2617         /*
2618          * The data structures could reference each other so we delete them in two phases.
2619          * This is required because of the hashing functions in gclass/ginst_cache.
2620          */
2621         ginst_data.image = gclass_data.image = image;
2622         ginst_data.list = gclass_data.list = NULL;
2623         mono_loader_lock ();
2624
2625         /* Collect the items to delete */
2626         /* delete_image_set () modifies the lists so make a copy */
2627         for (l = image->image_sets; l; l = l->next) {
2628                 MonoImageSet *set = l->data;
2629
2630                 g_hash_table_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
2631                 g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
2632                 g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
2633                 g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
2634         }
2635
2636         /* Delete the removed items */
2637         for (l = ginst_data.list; l; l = l->next)
2638                 free_generic_inst (l->data);
2639         for (l = gclass_data.list; l; l = l->next)
2640                 free_generic_class (l->data);
2641         g_slist_free (ginst_data.list);
2642         g_slist_free (gclass_data.list);
2643         /* delete_image_set () modifies the lists so make a copy */
2644         set_list = g_slist_copy (image->image_sets);
2645         for (l = set_list; l; l = l->next) {
2646                 MonoImageSet *set = l->data;
2647
2648                 delete_image_set (set);
2649         }
2650         g_slist_free (set_list);
2651
2652         mono_loader_unlock ();
2653
2654         return free_list;
2655 }
2656
2657 static void
2658 free_inflated_method (MonoMethodInflated *imethod)
2659 {
2660         int i;
2661         MonoMethod *method = (MonoMethod*)imethod;
2662
2663         mono_marshal_free_inflated_wrappers (method);
2664
2665         if (method->signature)
2666                 mono_metadata_free_inflated_signature (method->signature);
2667
2668         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))) {
2669                 MonoMethodHeader *header = imethod->header;
2670
2671                 if (header) {
2672                         /* Allocated in inflate_generic_header () */
2673                         for (i = 0; i < header->num_locals; ++i)
2674                                 mono_metadata_free_type (header->locals [i]);
2675                         g_free (header->clauses);
2676                         g_free (header);
2677                 }
2678         }
2679
2680         g_free (method);
2681 }
2682
2683 static void
2684 free_generic_inst (MonoGenericInst *ginst)
2685 {
2686         int i;
2687
2688         /* The ginst itself is allocated from the image set mempool */
2689         for (i = 0; i < ginst->type_argc; ++i)
2690                 mono_metadata_free_type (ginst->type_argv [i]);
2691 }
2692
2693 static void
2694 free_generic_class (MonoGenericClass *gclass)
2695 {
2696         /* The gclass itself is allocated from the image set mempool */
2697         if (gclass->is_dynamic)
2698                 mono_reflection_free_dynamic_generic_class (gclass);
2699 }
2700
2701 static void
2702 free_inflated_signature (MonoInflatedMethodSignature *sig)
2703 {
2704         mono_metadata_free_inflated_signature (sig->sig);
2705         g_free (sig);
2706 }
2707
2708 /*
2709  * LOCKING: assumes the loader lock is held.
2710  */
2711 MonoMethodInflated*
2712 mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
2713 {
2714         CollectData data;
2715         MonoImageSet *set;
2716
2717         collect_data_init (&data);
2718
2719         collect_method_images (method, &data);
2720
2721         set = get_image_set (data.images, data.nimages);
2722
2723         collect_data_free (&data);
2724
2725         if (cache) {
2726                 g_hash_table_insert (set->gmethod_cache, method, method);
2727
2728                 return method;
2729         } else {
2730                 return g_hash_table_lookup (set->gmethod_cache, method);
2731         }
2732 }
2733
2734 /*
2735  * mono_metadata_get_inflated_signature:
2736  *
2737  *   Given an inflated signature and a generic context, return a canonical copy of the 
2738  * signature. The returned signature might be equal to SIG or it might be a cached copy.
2739  */
2740 MonoMethodSignature *
2741 mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
2742 {
2743         MonoInflatedMethodSignature helper;
2744         MonoInflatedMethodSignature *res;
2745         CollectData data;
2746         MonoImageSet *set;
2747
2748         mono_loader_lock ();
2749
2750         helper.sig = sig;
2751         helper.context.class_inst = context->class_inst;
2752         helper.context.method_inst = context->method_inst;
2753
2754         collect_data_init (&data);
2755
2756         collect_inflated_signature_images (&helper, &data);
2757
2758         set = get_image_set (data.images, data.nimages);
2759
2760         collect_data_free (&data);
2761
2762         res = g_hash_table_lookup (set->gsignature_cache, &helper);
2763         if (!res) {
2764                 res = g_new0 (MonoInflatedMethodSignature, 1);
2765                 res->sig = sig;
2766                 res->context.class_inst = context->class_inst;
2767                 res->context.method_inst = context->method_inst;
2768                 g_hash_table_insert (set->gsignature_cache, res, res);
2769         }
2770
2771         mono_loader_unlock ();
2772         return res->sig;
2773 }
2774
2775 /*
2776  * mono_metadata_get_generic_inst:
2777  *
2778  * Given a list of types, return a MonoGenericInst that represents that list.
2779  * The returned MonoGenericInst has its own copy of the list of types.  The list
2780  * passed in the argument can be freed, modified or disposed of.
2781  *
2782  */
2783 MonoGenericInst *
2784 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
2785 {
2786         MonoGenericInst *ginst;
2787         gboolean is_open;
2788         int i;
2789         int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
2790         CollectData data;
2791         MonoImageSet *set;
2792
2793         for (i = 0; i < type_argc; ++i)
2794                 if (mono_class_is_open_constructed_type (type_argv [i]))
2795                         break;
2796         is_open = (i < type_argc);
2797
2798         ginst = alloca (size);
2799 #ifndef MONO_SMALL_CONFIG
2800         ginst->id = 0;
2801 #endif
2802         ginst->is_open = is_open;
2803         ginst->type_argc = type_argc;
2804         memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
2805
2806         mono_loader_lock ();
2807
2808         collect_data_init (&data);
2809
2810         collect_ginst_images (ginst, &data);
2811
2812         set = get_image_set (data.images, data.nimages);
2813
2814         collect_data_free (&data);
2815
2816         ginst = g_hash_table_lookup (set->ginst_cache, ginst);
2817         if (!ginst) {
2818                 ginst = mono_image_set_alloc0 (set, size);
2819 #ifndef MONO_SMALL_CONFIG
2820                 ginst->id = ++next_generic_inst_id;
2821 #endif
2822                 ginst->is_open = is_open;
2823                 ginst->type_argc = type_argc;
2824
2825                 for (i = 0; i < type_argc; ++i)
2826                         ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
2827
2828                 g_hash_table_insert (set->ginst_cache, ginst, ginst);
2829         }
2830
2831         mono_loader_unlock ();
2832         return ginst;
2833 }
2834
2835 static gboolean
2836 mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
2837 {
2838         MonoGenericContainer *container = container_class->generic_container; 
2839
2840         if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
2841                 return FALSE;
2842         return inst == container->context.class_inst;
2843 }
2844
2845 /*
2846  * mono_metadata_lookup_generic_class:
2847  *
2848  * Returns a MonoGenericClass with the given properties.
2849  *
2850  */
2851 MonoGenericClass *
2852 mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
2853 {
2854         MonoGenericClass *gclass;
2855         MonoGenericClass helper;
2856         gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
2857         MonoImageSet *set;
2858         CollectData data;
2859
2860         helper.container_class = container_class;
2861         helper.context.class_inst = inst;
2862         helper.context.method_inst = NULL;
2863         helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2864         helper.is_tb_open = is_tb_open;
2865         helper.cached_class = NULL;
2866
2867         mono_loader_lock ();
2868
2869         collect_data_init (&data);
2870
2871         collect_gclass_images (&helper, &data);
2872
2873         set = get_image_set (data.images, data.nimages);
2874
2875         collect_data_free (&data);
2876
2877         gclass = g_hash_table_lookup (set->gclass_cache, &helper);
2878
2879         /* A tripwire just to keep us honest */
2880         g_assert (!helper.cached_class);
2881
2882         if (gclass) {
2883                 mono_loader_unlock ();
2884                 return gclass;
2885         }
2886
2887         if (is_dynamic) {
2888                 MonoDynamicGenericClass *dgclass = mono_image_set_new0 (set, MonoDynamicGenericClass, 1);
2889                 gclass = &dgclass->generic_class;
2890                 gclass->is_dynamic = 1;
2891         } else {
2892                 gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
2893         }
2894
2895         gclass->is_tb_open = is_tb_open;
2896         gclass->container_class = container_class;
2897         gclass->context.class_inst = inst;
2898         gclass->context.method_inst = NULL;
2899         gclass->owner = set;
2900         if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
2901                 gclass->cached_class = container_class;
2902
2903         g_hash_table_insert (set->gclass_cache, gclass, gclass);
2904
2905         mono_loader_unlock ();
2906
2907         return gclass;
2908 }
2909
2910 /*
2911  * mono_metadata_inflate_generic_inst:
2912  *
2913  * Instantiate the generic instance @ginst with the context @context.
2914  * Check @error for success.
2915  *
2916  */
2917 MonoGenericInst *
2918 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
2919 {
2920         MonoType **type_argv;
2921         MonoGenericInst *nginst = NULL;
2922         int i, count = 0;
2923
2924         mono_error_init (error);
2925
2926         if (!ginst->is_open)
2927                 return ginst;
2928
2929         type_argv = g_new0 (MonoType*, ginst->type_argc);
2930
2931         for (i = 0; i < ginst->type_argc; i++) {
2932                 type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
2933                 if (!mono_error_ok (error))
2934                         goto cleanup;
2935                 ++count;
2936         }
2937
2938         nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
2939
2940 cleanup:
2941         for (i = 0; i < count; i++)
2942                 mono_metadata_free_type (type_argv [i]);
2943         g_free (type_argv);
2944
2945         return nginst;
2946 }
2947
2948 MonoGenericInst *
2949 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
2950                                   int count, const char *ptr, const char **rptr)
2951 {
2952         MonoType **type_argv;
2953         MonoGenericInst *ginst;
2954         int i;
2955
2956         type_argv = g_new0 (MonoType*, count);
2957
2958         for (i = 0; i < count; i++) {
2959                 MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
2960                 if (!t) {
2961                         g_free (type_argv);
2962                         return NULL;
2963                 }
2964                 type_argv [i] = t;
2965         }
2966
2967         if (rptr)
2968                 *rptr = ptr;
2969
2970         ginst = mono_metadata_get_generic_inst (count, type_argv);
2971
2972         g_free (type_argv);
2973
2974         return ginst;
2975 }
2976
2977 static gboolean
2978 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
2979                                       const char *ptr, const char **rptr)
2980 {
2981         MonoGenericInst *inst;
2982         MonoClass *gklass;
2983         MonoType *gtype;
2984         int count;
2985
2986         gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
2987         if (gtype == NULL)
2988                 return FALSE;
2989
2990         gklass = mono_class_from_mono_type (gtype);
2991         if (!gklass->generic_container)
2992                 return FALSE;
2993
2994         count = mono_metadata_decode_value (ptr, &ptr);
2995         inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
2996         if (inst == NULL)
2997                 return FALSE;
2998
2999         if (rptr)
3000                 *rptr = ptr;
3001
3002         type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
3003         return TRUE;
3004 }
3005
3006 /*
3007  * select_container:
3008  * @gc: The generic container to normalize
3009  * @type: The kind of generic parameters the resulting generic-container should contain
3010  */
3011
3012 static MonoGenericContainer *
3013 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
3014 {
3015         gboolean is_var = (type == MONO_TYPE_VAR);
3016         if (!gc)
3017                 return NULL;
3018
3019         g_assert (is_var || type == MONO_TYPE_MVAR);
3020
3021         if (is_var) {
3022                 if (gc->is_method || gc->parent)
3023                         /*
3024                          * The current MonoGenericContainer is a generic method -> its `parent'
3025                          * points to the containing class'es container.
3026                          */
3027                         return gc->parent;
3028         }
3029
3030         return gc;
3031 }
3032
3033 /* 
3034  * mono_metadata_parse_generic_param:
3035  * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3036  *                     see mono_metadata_parse_type_full() for details.
3037  * Internal routine to parse a generic type parameter.
3038  * LOCKING: Acquires the loader lock
3039  */
3040 static MonoGenericParam *
3041 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
3042                                    MonoTypeEnum type, const char *ptr, const char **rptr)
3043 {
3044         int index = mono_metadata_decode_value (ptr, &ptr);
3045         if (rptr)
3046                 *rptr = ptr;
3047
3048         generic_container = select_container (generic_container, type);
3049         if (!generic_container) {
3050                 /* Create dummy MonoGenericParam */
3051                 MonoGenericParam *param;
3052
3053                 param = mono_image_alloc0 (m, sizeof (MonoGenericParam));
3054                 param->num = index;
3055                 param->image = m;
3056
3057                 return param;
3058         }
3059
3060         if (index >= generic_container->type_argc)
3061                 return NULL;
3062
3063         return mono_generic_container_get_param (generic_container, index);
3064 }
3065
3066 /*
3067  * mono_metadata_get_shared_type:
3068  *
3069  *   Return a shared instance of TYPE, if available, NULL otherwise.
3070  * Shared MonoType instances help save memory. Their contents should not be modified
3071  * by the caller. They do not need to be freed as their lifetime is bound by either
3072  * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3073  * instance they are embedded in. If they are freed, they should be freed using
3074  * mono_metadata_free_type () instead of g_free ().
3075  */
3076 MonoType*
3077 mono_metadata_get_shared_type (MonoType *type)
3078 {
3079         MonoType *cached;
3080
3081         /* No need to use locking since nobody is modifying the hash table */
3082         if ((cached = g_hash_table_lookup (type_cache, type)))
3083                 return cached;
3084
3085         switch (type->type){
3086         case MONO_TYPE_CLASS:
3087         case MONO_TYPE_VALUETYPE:
3088                 if (type == &type->data.klass->byval_arg)
3089                         return type;
3090                 if (type == &type->data.klass->this_arg)
3091                         return type;
3092                 break;
3093         }
3094
3095         return NULL;
3096 }
3097
3098 /* 
3099  * do_mono_metadata_parse_type:
3100  * @type: MonoType to be filled in with the return value
3101  * @m: image context
3102  * @generic_context: generics_context
3103  * @transient: whenever to allocate data from the heap
3104  * @ptr: pointer to the encoded type
3105  * @rptr: pointer where the end of the encoded type is saved
3106  * 
3107  * Internal routine used to "fill" the contents of @type from an 
3108  * allocated pointer.  This is done this way to avoid doing too
3109  * many mini-allocations (particularly for the MonoFieldType which
3110  * most of the time is just a MonoType, but sometimes might be augmented).
3111  *
3112  * This routine is used by mono_metadata_parse_type and
3113  * mono_metadata_parse_field_type
3114  *
3115  * This extracts a Type as specified in Partition II (22.2.12) 
3116  *
3117  * Returns: FALSE if the type could not be loaded
3118  */
3119 static gboolean
3120 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3121                                                          gboolean transient, const char *ptr, const char **rptr)
3122 {
3123         gboolean ok = TRUE;
3124         type->type = mono_metadata_decode_value (ptr, &ptr);
3125         
3126         switch (type->type){
3127         case MONO_TYPE_VOID:
3128         case MONO_TYPE_BOOLEAN:
3129         case MONO_TYPE_CHAR:
3130         case MONO_TYPE_I1:
3131         case MONO_TYPE_U1:
3132         case MONO_TYPE_I2:
3133         case MONO_TYPE_U2:
3134         case MONO_TYPE_I4:
3135         case MONO_TYPE_U4:
3136         case MONO_TYPE_I8:
3137         case MONO_TYPE_U8:
3138         case MONO_TYPE_R4:
3139         case MONO_TYPE_R8:
3140         case MONO_TYPE_I:
3141         case MONO_TYPE_U:
3142         case MONO_TYPE_STRING:
3143         case MONO_TYPE_OBJECT:
3144         case MONO_TYPE_TYPEDBYREF:
3145                 break;
3146         case MONO_TYPE_VALUETYPE:
3147         case MONO_TYPE_CLASS: {
3148                 guint32 token;
3149                 MonoClass *class;
3150                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
3151                 class = mono_class_get (m, token);
3152                 type->data.klass = class;
3153                 if (!class)
3154                         return FALSE;
3155                 /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
3156                  * See mcs/test/gtest-440. and #650936.
3157                  * FIXME This better be moved to the metadata verifier as it can catch more cases.
3158                  */
3159                 if (class->byval_arg.type && class->byval_arg.type != type->type)
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 || idx < 0)
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
5219         mono_loader_lock ();
5220
5221         type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5222         if (type) {
5223                 mono_loader_unlock ();
5224                 return type;
5225         }
5226
5227         t = &image->tables [MONO_TABLE_TYPESPEC];
5228
5229         mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
5230         ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
5231
5232         if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
5233                 mono_loader_unlock ();
5234                 return NULL;
5235         }
5236
5237         len = mono_metadata_decode_value (ptr, &ptr);
5238
5239         type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
5240         if (!type) {
5241                 mono_loader_unlock ();
5242                 return NULL;
5243         }
5244
5245         type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5246
5247         if (type2) {
5248                 mono_loader_unlock ();
5249                 return type2;
5250         }
5251
5252         type2 = mono_metadata_type_dup (image, type);
5253         g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
5254         mono_metadata_free_type (type);
5255
5256         mono_loader_unlock ();
5257
5258         return type2;
5259 }
5260
5261
5262 static char*
5263 mono_image_strndup (MonoImage *image, const char *data, guint len)
5264 {
5265         char *res;
5266         if (!image)
5267                 return g_strndup (data, len);
5268         res = mono_image_alloc (image, len + 1);
5269         memcpy (res, data, len);
5270         res [len] = 0;
5271         return res;
5272 }
5273
5274 MonoMarshalSpec *
5275 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
5276 {
5277         return mono_metadata_parse_marshal_spec_full (NULL, ptr);
5278 }
5279
5280 MonoMarshalSpec *
5281 mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
5282 {
5283         MonoMarshalSpec *res;
5284         int len;
5285         const char *start = ptr;
5286
5287         /* fixme: this is incomplete, but I cant find more infos in the specs */
5288
5289         if (image)
5290                 res = mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
5291         else
5292                 res = g_new0 (MonoMarshalSpec, 1);
5293         
5294         len = mono_metadata_decode_value (ptr, &ptr);
5295         res->native = *ptr++;
5296
5297         if (res->native == MONO_NATIVE_LPARRAY) {
5298                 res->data.array_data.param_num = -1;
5299                 res->data.array_data.num_elem = -1;
5300                 res->data.array_data.elem_mult = -1;
5301
5302                 if (ptr - start <= len)
5303                         res->data.array_data.elem_type = *ptr++;
5304                 if (ptr - start <= len)
5305                         res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
5306                 if (ptr - start <= len)
5307                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5308                 if (ptr - start <= len) {
5309                         /*
5310                          * LAMESPEC: Older spec versions say this parameter comes before 
5311                          * num_elem. Never spec versions don't talk about elem_mult at
5312                          * all, but csc still emits it, and it is used to distinguish
5313                          * between param_num being 0, and param_num being omitted.
5314                          * So if (param_num == 0) && (num_elem > 0), then
5315                          * elem_mult == 0 -> the array size is num_elem
5316                          * elem_mult == 1 -> the array size is @param_num + num_elem
5317                          */
5318                         res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
5319                 }
5320         } 
5321
5322         if (res->native == MONO_NATIVE_BYVALTSTR) {
5323                 if (ptr - start <= len)
5324                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5325         }
5326
5327         if (res->native == MONO_NATIVE_BYVALARRAY) {
5328                 if (ptr - start <= len)
5329                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5330         }
5331         
5332         if (res->native == MONO_NATIVE_CUSTOM) {
5333                 /* skip unused type guid */
5334                 len = mono_metadata_decode_value (ptr, &ptr);
5335                 ptr += len;
5336                 /* skip unused native type name */
5337                 len = mono_metadata_decode_value (ptr, &ptr);
5338                 ptr += len;
5339                 /* read custom marshaler type name */
5340                 len = mono_metadata_decode_value (ptr, &ptr);
5341                 res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);               
5342                 ptr += len;
5343                 /* read cookie string */
5344                 len = mono_metadata_decode_value (ptr, &ptr);
5345                 res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
5346         }
5347
5348         if (res->native == MONO_NATIVE_SAFEARRAY) {
5349                 res->data.safearray_data.elem_type = 0;
5350                 res->data.safearray_data.num_elem = 0;
5351                 if (ptr - start <= len)
5352                         res->data.safearray_data.elem_type = *ptr++;
5353                 if (ptr - start <= len)
5354                         res->data.safearray_data.num_elem = *ptr++;
5355         }
5356         return res;
5357 }
5358
5359 void 
5360 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
5361 {
5362         if (spec->native == MONO_NATIVE_CUSTOM) {
5363                 g_free (spec->data.custom_data.custom_name);
5364                 g_free (spec->data.custom_data.cookie);
5365         }
5366         g_free (spec);
5367 }
5368
5369 /**
5370  * mono_type_to_unmanaged:
5371  *
5372  * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
5373  * describing the underlying native reprensetation of the type.
5374  * 
5375  * In addition the value pointed by
5376  * "conv" will contain the kind of marshalling required for this
5377  * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
5378  */
5379 guint32
5380 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
5381                         gboolean unicode, MonoMarshalConv *conv) 
5382 {
5383         MonoMarshalConv dummy_conv;
5384         int t = type->type;
5385
5386         if (!conv)
5387                 conv = &dummy_conv;
5388
5389         *conv = MONO_MARSHAL_CONV_NONE;
5390
5391         if (type->byref)
5392                 return MONO_NATIVE_UINT;
5393
5394 handle_enum:
5395         switch (t) {
5396         case MONO_TYPE_BOOLEAN: 
5397                 if (mspec) {
5398                         switch (mspec->native) {
5399                         case MONO_NATIVE_VARIANTBOOL:
5400                                 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
5401                                 return MONO_NATIVE_VARIANTBOOL;
5402                         case MONO_NATIVE_BOOLEAN:
5403                                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
5404                                 return MONO_NATIVE_BOOLEAN;
5405                         case MONO_NATIVE_I1:
5406                         case MONO_NATIVE_U1:
5407                                 return mspec->native;
5408                         default:
5409                                 g_error ("cant marshal bool to native type %02x", mspec->native);
5410                         }
5411                 }
5412                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
5413                 return MONO_NATIVE_BOOLEAN;
5414         case MONO_TYPE_CHAR:
5415                 if (mspec) {
5416                         switch (mspec->native) {
5417                         case MONO_NATIVE_U2:
5418                         case MONO_NATIVE_U1:
5419                                 return mspec->native;
5420                         default:
5421                                 g_error ("cant marshal char to native type %02x", mspec->native);
5422                         }
5423                 }
5424                 return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
5425         case MONO_TYPE_I1: return MONO_NATIVE_I1;
5426         case MONO_TYPE_U1: return MONO_NATIVE_U1;
5427         case MONO_TYPE_I2: return MONO_NATIVE_I2;
5428         case MONO_TYPE_U2: return MONO_NATIVE_U2;
5429         case MONO_TYPE_I4: return MONO_NATIVE_I4;
5430         case MONO_TYPE_U4: return MONO_NATIVE_U4;
5431         case MONO_TYPE_I8: return MONO_NATIVE_I8;
5432         case MONO_TYPE_U8: return MONO_NATIVE_U8;
5433         case MONO_TYPE_R4: return MONO_NATIVE_R4;
5434         case MONO_TYPE_R8: return MONO_NATIVE_R8;
5435         case MONO_TYPE_STRING:
5436                 if (mspec) {
5437                         switch (mspec->native) {
5438                         case MONO_NATIVE_BSTR:
5439                                 *conv = MONO_MARSHAL_CONV_STR_BSTR;
5440                                 return MONO_NATIVE_BSTR;
5441                         case MONO_NATIVE_LPSTR:
5442                                 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
5443                                 return MONO_NATIVE_LPSTR;
5444                         case MONO_NATIVE_LPWSTR:
5445                                 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
5446                                 return MONO_NATIVE_LPWSTR;
5447                         case MONO_NATIVE_LPTSTR:
5448                                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
5449                                 return MONO_NATIVE_LPTSTR;
5450                         case MONO_NATIVE_ANSIBSTR:
5451                                 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
5452                                 return MONO_NATIVE_ANSIBSTR;
5453                         case MONO_NATIVE_TBSTR:
5454                                 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
5455                                 return MONO_NATIVE_TBSTR;
5456                         case MONO_NATIVE_BYVALTSTR:
5457                                 if (unicode)
5458                                         *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
5459                                 else
5460                                         *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
5461                                 return MONO_NATIVE_BYVALTSTR;
5462                         default:
5463                                 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);
5464                         }
5465                 }       
5466                 if (unicode) {
5467                         *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
5468                         return MONO_NATIVE_LPWSTR; 
5469                 }
5470                 else {
5471                         *conv = MONO_MARSHAL_CONV_STR_LPSTR;
5472                         return MONO_NATIVE_LPSTR; 
5473                 }
5474         case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
5475         case MONO_TYPE_VALUETYPE: /*FIXME*/
5476                 if (type->data.klass->enumtype) {
5477                         t = mono_class_enum_basetype (type->data.klass)->type;
5478                         goto handle_enum;
5479                 }
5480                 if (type->data.klass == mono_defaults.handleref_class){
5481                         *conv = MONO_MARSHAL_CONV_HANDLEREF;
5482                         return MONO_NATIVE_INT;
5483                 }
5484                 return MONO_NATIVE_STRUCT;
5485         case MONO_TYPE_SZARRAY: 
5486         case MONO_TYPE_ARRAY: 
5487                 if (mspec) {
5488                         switch (mspec->native) {
5489                         case MONO_NATIVE_BYVALARRAY:
5490                                 if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
5491                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
5492                                 else
5493                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
5494                                 return MONO_NATIVE_BYVALARRAY;
5495                         case MONO_NATIVE_SAFEARRAY:
5496                                 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
5497                                 return MONO_NATIVE_SAFEARRAY;
5498                         case MONO_NATIVE_LPARRAY:                               
5499                                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
5500                                 return MONO_NATIVE_LPARRAY;
5501                         default:
5502                                 g_error ("cant marshal array as native type %02x", mspec->native);
5503                         }
5504                 }       
5505
5506                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
5507                 return MONO_NATIVE_LPARRAY;
5508         case MONO_TYPE_I: return MONO_NATIVE_INT;
5509         case MONO_TYPE_U: return MONO_NATIVE_UINT;
5510         case MONO_TYPE_CLASS: 
5511         case MONO_TYPE_OBJECT: {
5512                 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
5513                 if (mspec) {
5514                         switch (mspec->native) {
5515                         case MONO_NATIVE_STRUCT:
5516                                 return MONO_NATIVE_STRUCT;
5517                         case MONO_NATIVE_CUSTOM:
5518                                 return MONO_NATIVE_CUSTOM;
5519                         case MONO_NATIVE_INTERFACE:
5520                                 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
5521                                 return MONO_NATIVE_INTERFACE;
5522                         case MONO_NATIVE_IDISPATCH:
5523                                 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
5524                                 return MONO_NATIVE_IDISPATCH;
5525                         case MONO_NATIVE_IUNKNOWN:
5526                                 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
5527                                 return MONO_NATIVE_IUNKNOWN;
5528                         case MONO_NATIVE_FUNC:
5529                                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
5530                                                                                          type->data.klass == mono_defaults.delegate_class || 
5531                                                                                          type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
5532                                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
5533                                         return MONO_NATIVE_FUNC;
5534                                 }
5535                                 /* Fall through */
5536                         default:
5537                                 g_error ("cant marshal object as native type %02x", mspec->native);
5538                         }
5539                 }
5540                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
5541                                              type->data.klass == mono_defaults.delegate_class || 
5542                                              type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
5543                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
5544                         return MONO_NATIVE_FUNC;
5545                 }
5546                 if (mono_defaults.safehandle_class && type->data.klass == mono_defaults.safehandle_class){
5547                         *conv = MONO_MARSHAL_CONV_SAFEHANDLE;
5548                         return MONO_NATIVE_INT;
5549                 }
5550                 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
5551                 return MONO_NATIVE_STRUCT;
5552         }
5553         case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
5554         case MONO_TYPE_GENERICINST:
5555                 type = &type->data.generic_class->container_class->byval_arg;
5556                 t = type->type;
5557                 goto handle_enum;
5558         case MONO_TYPE_TYPEDBYREF:
5559         default:
5560                 g_error ("type 0x%02x not handled in marshal", t);
5561         }
5562         return MONO_NATIVE_MAX;
5563 }
5564
5565 const char*
5566 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
5567 {
5568         locator_t loc;
5569         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_FIELDMARSHAL];
5570
5571         if (!tdef->base)
5572                 return NULL;
5573
5574         loc.t = tdef;
5575         loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
5576         loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
5577
5578         /* FIXME: Index translation */
5579
5580         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5581                 return NULL;
5582
5583         return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
5584 }
5585
5586 MonoMethod*
5587 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
5588 {
5589         guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
5590
5591         switch (tok & MONO_METHODDEFORREF_MASK) {
5592         case MONO_METHODDEFORREF_METHODDEF:
5593                 return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
5594         case MONO_METHODDEFORREF_METHODREF:
5595                 return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
5596         }
5597         g_assert_not_reached ();
5598         return NULL;
5599 }
5600
5601 /*
5602  * mono_class_get_overrides_full:
5603  *
5604  *   Return the method overrides belonging to class @type_token in @overrides, and
5605  * the number of overrides in @num_overrides.
5606  *
5607  * Returns: TRUE on success, FALSE on failure.
5608  */
5609 gboolean
5610 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
5611                                MonoGenericContext *generic_context)
5612 {
5613         MonoError error;
5614         locator_t loc;
5615         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
5616         guint32 start, end;
5617         gint32 i, num;
5618         guint32 cols [MONO_METHODIMPL_SIZE];
5619         MonoMethod **result;
5620         gint32 ok = TRUE;
5621         
5622         *overrides = NULL;
5623         if (num_overrides)
5624                 *num_overrides = 0;
5625
5626         if (!tdef->base)
5627                 return TRUE;
5628
5629         loc.t = tdef;
5630         loc.col_idx = MONO_METHODIMPL_CLASS;
5631         loc.idx = mono_metadata_token_index (type_token);
5632
5633         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5634                 return TRUE;
5635
5636         start = loc.result;
5637         end = start + 1;
5638         /*
5639          * We may end up in the middle of the rows... 
5640          */
5641         while (start > 0) {
5642                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
5643                         start--;
5644                 else
5645                         break;
5646         }
5647         while (end < tdef->rows) {
5648                 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
5649                         end++;
5650                 else
5651                         break;
5652         }
5653         num = end - start;
5654         result = g_new (MonoMethod*, num * 2);
5655         for (i = 0; i < num; ++i) {
5656                 MonoMethod *method;
5657
5658                 if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
5659                         mono_error_cleanup (&error);
5660                         ok = FALSE;
5661                         break;
5662                 }
5663
5664                 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
5665                 method = method_from_method_def_or_ref (
5666                         image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
5667                 if (method == NULL)
5668                         ok = FALSE;
5669                 result [i * 2] = method;
5670                 method = method_from_method_def_or_ref (
5671                         image, cols [MONO_METHODIMPL_BODY], generic_context);
5672                 if (method == NULL)
5673                         ok = FALSE;
5674                 result [i * 2 + 1] = method;
5675         }
5676
5677         *overrides = result;
5678         if (num_overrides)
5679                 *num_overrides = num;
5680         return ok;
5681 }
5682
5683 /**
5684  * mono_guid_to_string:
5685  *
5686  * Converts a 16 byte Microsoft GUID to the standard string representation.
5687  */
5688 char *
5689 mono_guid_to_string (const guint8 *guid)
5690 {
5691         return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
5692                                 guid[3], guid[2], guid[1], guid[0],
5693                                 guid[5], guid[4],
5694                                 guid[7], guid[6],
5695                                 guid[8], guid[9],
5696                                 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
5697 }
5698
5699 static gboolean
5700 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
5701 {
5702         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
5703         guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
5704         guint32 i, token, found;
5705         MonoClass *klass, **res;
5706         GSList *cons = NULL, *tmp;
5707         MonoGenericContext *context = &container->context;
5708
5709         *constraints = NULL;
5710         found = 0;
5711         for (i = 0; i < tdef->rows; ++i) {
5712                 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
5713                 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
5714                         token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
5715                         klass = mono_class_get_full (image, token, context);
5716                         if (!klass) {
5717                                 g_slist_free (cons);
5718                                 return FALSE;
5719                         }
5720                         cons = g_slist_append (cons, klass);
5721                         ++found;
5722                 } else {
5723                         /* contiguous list finished */
5724                         if (found)
5725                                 break;
5726                 }
5727         }
5728         if (!found)
5729                 return TRUE;
5730         res = mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
5731         for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
5732                 res [i] = tmp->data;
5733         }
5734         g_slist_free (cons);
5735         *constraints = res;
5736         return TRUE;
5737 }
5738
5739 /*
5740  * mono_metadata_get_generic_param_row:
5741  *
5742  * @image:
5743  * @token: TypeOrMethodDef token, owner for GenericParam
5744  * @owner: coded token, set on return
5745  * 
5746  * Returns: 1-based row-id in the GenericParam table whose
5747  * owner is @token. 0 if not found.
5748  */
5749 guint32
5750 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
5751 {
5752         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
5753         locator_t loc;
5754
5755         g_assert (owner);
5756         if (!tdef->base)
5757                 return 0;
5758
5759         if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
5760                 *owner = MONO_TYPEORMETHOD_TYPE;
5761         else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
5762                 *owner = MONO_TYPEORMETHOD_METHOD;
5763         else {
5764                 g_error ("wrong token %x to get_generic_param_row", token);
5765                 return 0;
5766         }
5767         *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
5768
5769         loc.idx = *owner;
5770         loc.col_idx = MONO_GENERICPARAM_OWNER;
5771         loc.t = tdef;
5772
5773         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5774                 return 0;
5775
5776         /* Find the first entry by searching backwards */
5777         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
5778                 loc.result --;
5779
5780         return loc.result + 1;
5781 }
5782
5783 gboolean
5784 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
5785 {
5786         guint32 owner;
5787         return mono_metadata_get_generic_param_row (image, token, &owner);
5788 }
5789
5790 /*
5791  * Memory is allocated from IMAGE's mempool.
5792  */
5793 gboolean
5794 mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
5795                                               MonoGenericContainer *container)
5796 {
5797
5798         guint32 start_row, i, owner;
5799         if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
5800                 return TRUE;
5801         for (i = 0; i < container->type_argc; i++) {
5802                 if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container))
5803                         return FALSE;
5804         }
5805         return TRUE;
5806 }
5807
5808 /*
5809  * mono_metadata_load_generic_param_constraints:
5810  *
5811  * @image: metadata context
5812  * @token: metadata token to load the contraints, can be methodef or typedef.
5813  * @container: generic container to load into.
5814  *
5815  * Load the generic parameter constraints for the newly created generic type or method
5816  * represented by @token and @container.  The @container is the new container which has
5817  * been returned by a call to mono_metadata_load_generic_params() with this @token.
5818  * Memory is allocated from IMAGE's mempool.
5819  */
5820 void
5821 mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
5822                                               MonoGenericContainer *container)
5823 {
5824         mono_metadata_load_generic_param_constraints_full (image, token, container);
5825         /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
5826 }
5827
5828 /*
5829  * mono_metadata_load_generic_params:
5830  *
5831  * Load the type parameters from the type or method definition @token.
5832  *
5833  * Use this method after parsing a type or method definition to figure out whether it's a generic
5834  * type / method.  When parsing a method definition, @parent_container points to the generic container
5835  * of the current class, if any.
5836  *
5837  * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5838  *       creating the type.
5839  *
5840  * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5841  *
5842  * LOCKING: Acquires the loader lock
5843  *
5844  */
5845 MonoGenericContainer *
5846 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
5847 {
5848         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
5849         guint32 cols [MONO_GENERICPARAM_SIZE];
5850         guint32 i, owner = 0, n;
5851         MonoGenericContainer *container;
5852         MonoGenericParamFull *params;
5853         MonoGenericContext *context;
5854
5855         if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
5856                 return NULL;
5857         mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
5858         params = NULL;
5859         n = 0;
5860         container = mono_image_alloc0 (image, sizeof (MonoGenericContainer));
5861         container->image = image;
5862         do {
5863                 n++;
5864                 params = g_realloc (params, sizeof (MonoGenericParamFull) * n);
5865                 memset (&params [n - 1], 0, sizeof (MonoGenericParamFull));
5866                 params [n - 1].param.owner = container;
5867                 params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
5868                 params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
5869                 params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
5870                 params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
5871                 if (params [n - 1].param.num != n - 1)
5872                         g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
5873                 if (++i > tdef->rows)
5874                         break;
5875                 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
5876         } while (cols [MONO_GENERICPARAM_OWNER] == owner);
5877
5878         container->type_argc = n;
5879         container->type_params = mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
5880         memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
5881         g_free (params);
5882         container->parent = parent_container;
5883
5884         if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
5885                 container->is_method = 1;
5886
5887         g_assert (container->parent == NULL || container->is_method);
5888
5889         context = &container->context;
5890         if (container->is_method) {
5891                 context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
5892                 context->method_inst = mono_get_shared_generic_inst (container);
5893         } else {
5894                 context->class_inst = mono_get_shared_generic_inst (container);
5895         }
5896
5897         return container;
5898 }
5899
5900 MonoGenericInst *
5901 mono_get_shared_generic_inst (MonoGenericContainer *container)
5902 {
5903         MonoType **type_argv;
5904         MonoType *helper;
5905         MonoGenericInst *nginst;
5906         int i;
5907
5908         type_argv = g_new0 (MonoType *, container->type_argc);
5909         helper = g_new0 (MonoType, container->type_argc);
5910
5911         for (i = 0; i < container->type_argc; i++) {
5912                 MonoType *t = &helper [i];
5913
5914                 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5915                 t->data.generic_param = mono_generic_container_get_param (container, i);
5916
5917                 type_argv [i] = t;
5918         }
5919
5920         nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
5921
5922         g_free (type_argv);
5923         g_free (helper);
5924
5925         return nginst;
5926 }
5927
5928 /**
5929  * mono_type_is_byref:
5930  * @type: the MonoType operated on
5931  *
5932  * Returns: #TRUE if @type represents a type passed by reference,
5933  * #FALSE otherwise.
5934  */
5935 gboolean
5936 mono_type_is_byref (MonoType *type)
5937 {
5938         return type->byref;
5939 }
5940
5941 /**
5942  * mono_type_get_type:
5943  * @type: the MonoType operated on
5944  *
5945  * Returns: the IL type value for @type. This is one of the MonoTypeEnum
5946  * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
5947  */
5948 int
5949 mono_type_get_type (MonoType *type)
5950 {
5951         return type->type;
5952 }
5953
5954 /**
5955  * mono_type_get_signature:
5956  * @type: the MonoType operated on
5957  *
5958  * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
5959  *
5960  * Returns: the MonoMethodSignature pointer that describes the signature
5961  * of the function pointer @type represents.
5962  */
5963 MonoMethodSignature*
5964 mono_type_get_signature (MonoType *type)
5965 {
5966         g_assert (type->type == MONO_TYPE_FNPTR);
5967         return type->data.method;
5968 }
5969
5970 /**
5971  * mono_type_get_class:
5972  * @type: the MonoType operated on
5973  *
5974  * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
5975  * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
5976  * instead
5977  *
5978  * Returns: the MonoClass pointer that describes the class that @type represents.
5979  */
5980 MonoClass*
5981 mono_type_get_class (MonoType *type)
5982 {
5983         /* FIXME: review the runtime users before adding the assert here */
5984         return type->data.klass;
5985 }
5986
5987 /**
5988  * mono_type_get_array_type:
5989  * @type: the MonoType operated on
5990  *
5991  * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
5992  *
5993  * Returns: a MonoArrayType struct describing the array type that @type
5994  * represents. The info includes details such as rank, array element type
5995  * and the sizes and bounds of multidimensional arrays.
5996  */
5997 MonoArrayType*
5998 mono_type_get_array_type (MonoType *type)
5999 {
6000         return type->data.array;
6001 }
6002
6003 /**
6004  * mono_type_get_ptr_type:
6005  * @type: the MonoType operated on
6006  *
6007  * It is only valid to call this function if @type is a MONO_TYPE_PTR.
6008  * instead
6009  *
6010  * Returns: the MonoType pointer that describes the type that @type
6011  * represents a pointer to.
6012  */
6013 MonoType*
6014 mono_type_get_ptr_type (MonoType *type)
6015 {
6016         g_assert (type->type == MONO_TYPE_PTR);
6017         return type->data.type;
6018 }
6019
6020 MonoClass*
6021 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
6022 {
6023         /* FIXME: implement */
6024         return NULL;
6025 }
6026
6027 /**
6028  * mono_type_is_struct:
6029  * @type: the MonoType operated on
6030  *
6031  * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
6032  * or a basic type like System.Int32. #FALSE otherwise.
6033  */
6034 mono_bool
6035 mono_type_is_struct (MonoType *type)
6036 {
6037         return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
6038                 !type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
6039                 ((type->type == MONO_TYPE_GENERICINST) && 
6040                 mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
6041                 !type->data.generic_class->container_class->enumtype)));
6042 }
6043
6044 /**
6045  * mono_type_is_void:
6046  * @type: the MonoType operated on
6047  *
6048  * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
6049  */
6050 mono_bool
6051 mono_type_is_void (MonoType *type)
6052 {
6053         return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
6054 }
6055
6056 /**
6057  * mono_type_is_pointer:
6058  * @type: the MonoType operated on
6059  *
6060  * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
6061  */
6062 mono_bool
6063 mono_type_is_pointer (MonoType *type)
6064 {
6065         return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
6066                 || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6067                 (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
6068                 (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
6069                 (type->type == MONO_TYPE_FNPTR)));
6070 }
6071
6072 /**
6073  * mono_type_is_reference:
6074  * @type: the MonoType operated on
6075  *
6076  * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
6077  */
6078 mono_bool
6079 mono_type_is_reference (MonoType *type)
6080 {
6081         return (type && (((type->type == MONO_TYPE_STRING) ||
6082                 (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6083                 (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
6084                 ((type->type == MONO_TYPE_GENERICINST) &&
6085                 !mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
6086 }
6087
6088 /**
6089  * mono_signature_get_return_type:
6090  * @sig: the method signature inspected
6091  *
6092  * Returns: the return type of the method signature @sig
6093  */
6094 MonoType*
6095 mono_signature_get_return_type (MonoMethodSignature *sig)
6096 {
6097         return sig->ret;
6098 }
6099
6100 /**
6101  * mono_signature_get_params:
6102  * @sig: the method signature inspected
6103  * #iter: pointer to an iterator
6104  *
6105  * Iterates over the parameters for the method signature @sig.
6106  * A void* pointer must be initualized to #NULL to start the iteration
6107  * and it's address is passed to this function repeteadly until it returns
6108  * #NULL.
6109  *
6110  * Returns: the next parameter type of the method signature @sig,
6111  * #NULL when finished.
6112  */
6113 MonoType*
6114 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
6115 {
6116         MonoType** type;
6117         if (!iter)
6118                 return NULL;
6119         if (!*iter) {
6120                 /* start from the first */
6121                 if (sig->param_count) {
6122                         *iter = &sig->params [0];
6123                         return sig->params [0];
6124                 } else {
6125                         /* no method */
6126                         return NULL;
6127                 }
6128         }
6129         type = *iter;
6130         type++;
6131         if (type < &sig->params [sig->param_count]) {
6132                 *iter = type;
6133                 return *type;
6134         }
6135         return NULL;
6136 }
6137
6138 /**
6139  * mono_signature_get_param_count:
6140  * @sig: the method signature inspected
6141  *
6142  * Returns: the number of parameters in the method signature @sig.
6143  */
6144 guint32
6145 mono_signature_get_param_count (MonoMethodSignature *sig)
6146 {
6147         return sig->param_count;
6148 }
6149
6150 /**
6151  * mono_signature_get_call_conv:
6152  * @sig: the method signature inspected
6153  *
6154  * Returns: the call convention of the method signature @sig.
6155  */
6156 guint32
6157 mono_signature_get_call_conv (MonoMethodSignature *sig)
6158 {
6159         return sig->call_convention;
6160 }
6161
6162 /**
6163  * mono_signature_vararg_start:
6164  * @sig: the method signature inspected
6165  *
6166  * Returns: the number of the first vararg parameter in the
6167  * method signature @sig. -1 if this is not a vararg signature.
6168  */
6169 int
6170 mono_signature_vararg_start (MonoMethodSignature *sig)
6171 {
6172         return sig->sentinelpos;
6173 }
6174
6175 /**
6176  * mono_signature_is_instance:
6177  * @sig: the method signature inspected
6178  *
6179  * Returns: #TRUE if this the method signature @sig has an implicit
6180  * first instance argument. #FALSE otherwise.
6181  */
6182 gboolean
6183 mono_signature_is_instance (MonoMethodSignature *sig)
6184 {
6185         return sig->hasthis;
6186 }
6187
6188 /**
6189  * mono_signature_explicit_this:
6190  * @sig: the method signature inspected
6191  *
6192  * Returns: #TRUE if this the method signature @sig has an explicit
6193  * instance argument. #FALSE otherwise.
6194  */
6195 gboolean
6196 mono_signature_explicit_this (MonoMethodSignature *sig)
6197 {
6198         return sig->explicit_this;
6199 }
6200
6201 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6202 guint
6203 mono_aligned_addr_hash (gconstpointer ptr)
6204 {
6205         return GPOINTER_TO_UINT (ptr) >> 3;
6206 }
6207
6208 /*
6209  * If @field belongs to an inflated generic class, return the corresponding field of the
6210  * generic type definition class.
6211  */
6212 MonoClassField*
6213 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
6214 {
6215         MonoClass *gtd;
6216         int offset;
6217
6218         if (!field->parent->generic_class)
6219                 return field;
6220
6221         gtd = field->parent->generic_class->container_class;
6222         offset = field - field->parent->fields;
6223         return gtd->fields + offset;
6224 }
6225
6226 /*
6227  * If @event belongs to an inflated generic class, return the corresponding event of the
6228  * generic type definition class.
6229  */
6230 MonoEvent*
6231 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
6232 {
6233         MonoClass *gtd;
6234         int offset;
6235
6236         if (!event->parent->generic_class)
6237                 return event;
6238
6239         gtd = event->parent->generic_class->container_class;
6240         offset = event - event->parent->ext->events;
6241         return gtd->ext->events + offset;
6242 }
6243
6244 /*
6245  * If @property belongs to an inflated generic class, return the corresponding property of the
6246  * generic type definition class.
6247  */
6248 MonoProperty*
6249 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
6250 {
6251         MonoClass *gtd;
6252         int offset;
6253
6254         if (!property->parent->generic_class)
6255                 return property;
6256
6257         gtd = property->parent->generic_class->container_class;
6258         offset = property - property->parent->ext->properties;
6259         return gtd->ext->properties + offset;
6260 }
6261