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