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