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