2004-08-04 Bernie Solomon <bernard@ugsolutions.com>
[mono.git] / mono / metadata / class.c
1 /*
2  * class.c: Class management for the Mono runtime
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  *
9  * Possible Optimizations:
10  *     in mono_class_create, do not allocate the class right away,
11  *     but wait until you know the size of the FieldMap, so that
12  *     the class embeds directly the FieldMap after the vtable.
13  *
14  * 
15  */
16 #include <config.h>
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/cil-coff.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/os/gc_wrapper.h>
36
37 MonoStats mono_stats;
38
39 gboolean mono_print_vtable = FALSE;
40
41 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
42
43 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
44 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
45
46 MonoClass *
47 mono_class_from_typeref (MonoImage *image, guint32 type_token)
48 {
49         guint32 cols [MONO_TYPEREF_SIZE];
50         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
51         guint32 idx;
52         const char *name, *nspace;
53         MonoClass *res;
54         MonoAssembly **references;
55
56         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
57
58         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
59         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
60         
61         idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
62         switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
63         case MONO_RESOLTION_SCOPE_MODULE:
64                 if (!idx)
65                         g_error ("null ResolutionScope not yet handled");
66                 /* a typedef in disguise */
67                 return mono_class_from_name (image, nspace, name);
68         case MONO_RESOLTION_SCOPE_MODULEREF:
69                 return mono_class_from_name (image->modules [idx - 1], nspace, name);
70         case MONO_RESOLTION_SCOPE_TYPEREF: {
71                 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
72                 GList *tmp;
73                 mono_class_init (enclosing);
74                 for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
75                         res = tmp->data;
76                         if (strcmp (res->name, name) == 0)
77                                 return res;
78                 }
79                 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
80                 return NULL;
81         }
82         case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
83                 break;
84         }
85
86         references = image->references;
87         if (!references ||  !references [idx-1]) {
88                 /* 
89                  * detected a reference to mscorlib, we simply return a reference to a dummy 
90                  * until we have a better solution.
91                  * 
92                  * once a better solution is in place, the System.MonoDummy
93                  * class should be removed from CVS.
94                  */
95                 fprintf(stderr, "Sending dummy where %s.%s expected\n", mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]), mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME])); 
96                 
97                 res = mono_class_from_name (image, "System", "MonoDummy");
98                 /* prevent method loading */
99                 res->dummy = 1;
100                 /* some storage if the type is used  - very ugly hack */
101                 res->instance_size = 2*sizeof (gpointer);
102                 return res;
103         }       
104
105         /* load referenced assembly */
106         image = references [idx-1]->image;
107
108         return mono_class_from_name (image, nspace, name);
109 }
110
111 static MonoType*
112 dup_type (MonoType* t, const MonoType *original)
113 {
114         MonoType *r = g_new0 (MonoType, 1);
115         *r = *t;
116         r->attrs = original->attrs;
117         mono_stats.generics_metadata_size += sizeof (MonoType);
118         return r;
119 }
120
121 static void
122 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
123                             gboolean include_arity)
124 {
125         MonoClass *klass;
126         
127         switch (type->type) {
128         case MONO_TYPE_ARRAY: {
129                 int i, rank = type->data.array->rank;
130
131                 mono_type_get_name_recurse (
132                         &type->data.array->eklass->byval_arg, str, FALSE, include_arity);
133                 g_string_append_c (str, '[');
134                 for (i = 1; i < rank; i++)
135                         g_string_append_c (str, ',');
136                 g_string_append_c (str, ']');
137                 break;
138         }
139         case MONO_TYPE_SZARRAY:
140                 mono_type_get_name_recurse (
141                         &type->data.klass->byval_arg, str, FALSE, include_arity);
142                 g_string_append (str, "[]");
143                 break;
144         case MONO_TYPE_PTR:
145                 mono_type_get_name_recurse (type->data.type, str, FALSE, include_arity);
146                 g_string_append_c (str, '*');
147                 break;
148         default:
149                 klass = mono_class_from_mono_type (type);
150                 if (klass->nested_in) {
151                         mono_type_get_name_recurse (
152                                 &klass->nested_in->byval_arg, str, TRUE, include_arity);
153                         g_string_append_c (str, '+');
154                 }
155                 if (*klass->name_space) {
156                         g_string_append (str, klass->name_space);
157                         g_string_append_c (str, '.');
158                 }
159                 if (!include_arity) {
160                         char *s = strchr (klass->name, '`');
161                         int len = s ? s - klass->name : strlen (klass->name);
162
163                         g_string_append_len (str, klass->name, len);
164                 } else
165                         g_string_append (str, klass->name);
166                 if (is_recursed)
167                         break;
168                 if (klass->generic_inst) {
169                         MonoGenericInst *ginst = klass->generic_inst;
170                         int i;
171
172                         g_string_append_c (str, '<');
173                         for (i = 0; i < ginst->type_argc; i++) {
174                                 if (i)
175                                         g_string_append_c (str, ',');
176                                 mono_type_get_name_recurse (
177                                         ginst->type_argv [i], str, FALSE, include_arity);
178                         }
179                         g_string_append_c (str, '>');
180                 } else if (klass->gen_params) {
181                         int i;
182
183                         g_string_append_c (str, '<');
184                         for (i = 0; i < klass->num_gen_params; i++) {
185                                 if (i)
186                                         g_string_append_c (str, ',');
187                                 g_string_append (str, klass->gen_params [i].name);
188                         }
189                         g_string_append_c (str, '>');
190                 }
191                 break;
192         }
193 }
194
195 /*
196  * mono_type_get_name:
197  * @type: a type
198  *
199  * Returns the string representation for type as required by System.Reflection.
200  * The inverse of mono_reflection_parse_type ().
201  */
202 static char*
203 _mono_type_get_name (MonoType *type, gboolean include_arity)
204 {
205         GString* result = g_string_new ("");
206         mono_type_get_name_recurse (type, result, FALSE, include_arity);
207
208         if (type->byref)
209                 g_string_append_c (result, '&');
210
211         return g_string_free (result, FALSE);
212 }
213
214 char*
215 mono_type_get_name (MonoType *type)
216 {
217         return _mono_type_get_name (type, TRUE);
218 }
219
220 gboolean
221 mono_class_is_open_constructed_type (MonoType *t)
222 {
223         switch (t->type) {
224         case MONO_TYPE_VAR:
225         case MONO_TYPE_MVAR:
226                 return TRUE;
227         case MONO_TYPE_SZARRAY:
228                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
229         case MONO_TYPE_ARRAY:
230                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
231         case MONO_TYPE_PTR:
232                 return mono_class_is_open_constructed_type (t->data.type);
233         case MONO_TYPE_GENERICINST: {
234                 MonoGenericInst *ginst = t->data.generic_inst;
235                 int i;
236
237                 if (mono_class_is_open_constructed_type (ginst->generic_type))
238                         return TRUE;
239                 for (i = 0; i < ginst->type_argc; i++)
240                         if (mono_class_is_open_constructed_type (ginst->type_argv [i]))
241                                 return TRUE;
242                 return FALSE;
243         }
244         default:
245                 return FALSE;
246         }
247 }
248
249 static MonoType*
250 inflate_generic_type (MonoType *type, MonoGenericContext *context)
251 {
252         switch (type->type) {
253         case MONO_TYPE_MVAR:
254                 if (context->gmethod && context->gmethod->mtype_argv)
255                         return dup_type (
256                                 context->gmethod->mtype_argv [type->data.generic_param->num],
257                                 type);
258                 else
259                         return NULL;
260         case MONO_TYPE_VAR:
261                 if (context->ginst)
262                         return dup_type (
263                                 context->ginst->type_argv [type->data.generic_param->num],
264                                 type);
265                 else
266                         return NULL;
267         case MONO_TYPE_SZARRAY: {
268                 MonoClass *eclass = type->data.klass;
269                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
270                 if (!inflated)
271                         return NULL;
272                 nt = dup_type (type, type);
273                 nt->data.klass = mono_class_from_mono_type (inflated);
274                 return nt;
275         }
276         case MONO_TYPE_GENERICINST: {
277                 MonoGenericInst *oginst = type->data.generic_inst;
278                 MonoGenericInst *nginst;
279                 MonoType *nt;
280                 int i;
281
282                 nginst = g_new0 (MonoGenericInst, 1);
283                 *nginst = *oginst;
284
285                 nginst->is_open = FALSE;
286
287                 nginst->type_argv = g_new0 (MonoType *, oginst->type_argc);
288
289                 for (i = 0; i < oginst->type_argc; i++) {
290                         MonoType *t = oginst->type_argv [i];
291                         nginst->type_argv [i] = mono_class_inflate_generic_type (t, context);
292
293                         if (!nginst->is_open)
294                                 nginst->is_open = mono_class_is_open_constructed_type (nginst->type_argv [i]);
295                 };
296
297                 nginst->klass = NULL;
298
299                 nginst->context = g_new0 (MonoGenericContext, 1);
300                 nginst->context->ginst = nginst;
301
302                 mono_loader_lock ();
303                 nt = g_hash_table_lookup (oginst->klass->image->generic_inst_cache, nginst);
304
305                 if (nt) {
306                         g_free (nginst->type_argv);
307                         g_free (nginst);
308                         mono_loader_unlock ();
309                         return nt;
310                 }
311
312                 nginst->dynamic_info = NULL;
313                 nginst->initialized = FALSE;
314
315                 mono_class_create_generic (nginst);
316
317                 mono_stats.generic_instance_count++;
318                 mono_stats.generics_metadata_size += sizeof (MonoGenericInst) +
319                         sizeof (MonoGenericContext) +
320                         nginst->type_argc * sizeof (MonoType);
321
322                 nt = dup_type (type, type);
323                 nt->data.generic_inst = nginst;
324                 g_hash_table_insert (oginst->klass->image->generic_inst_cache, nginst, nt);
325                 mono_loader_unlock ();
326                 return nt;
327         }
328         default:
329                 return NULL;
330         }
331         return NULL;
332 }
333
334 MonoType*
335 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
336 {
337         MonoType *inflated = inflate_generic_type (type, context);
338
339         if (!inflated)
340                 return type;
341
342         mono_stats.inflated_type_count++;
343         return inflated;
344 }
345
346 static MonoMethodSignature*
347 inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
348                            MonoGenericContext *context)
349 {
350         MonoMethodSignature *res;
351         int i;
352         res = mono_metadata_signature_alloc (image, sig->param_count);
353         res->ret = mono_class_inflate_generic_type (sig->ret, context);
354         for (i = 0; i < sig->param_count; ++i)
355                 res->params [i] = mono_class_inflate_generic_type (sig->params [i], context);
356         res->hasthis = sig->hasthis;
357         res->explicit_this = sig->explicit_this;
358         res->call_convention = sig->call_convention;
359         res->generic_param_count = sig->generic_param_count;
360         res->is_inflated = 1;
361         return res;
362 }
363
364 static MonoMethodHeader*
365 inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
366 {
367         MonoMethodHeader *res;
368         int i;
369         res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
370         res->code = header->code;
371         res->code_size = header->code_size;
372         res->max_stack = header->max_stack;
373         res->num_clauses = header->num_clauses;
374         res->init_locals = header->init_locals;
375         res->num_locals = header->num_locals;
376         res->clauses = header->clauses;
377         res->gen_params = header->gen_params;
378         for (i = 0; i < header->num_locals; ++i)
379                 res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context);
380         return res;
381 }
382
383 MonoMethod*
384 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context,
385                                    MonoClass *klass)
386 {
387         MonoMethodInflated *result;
388
389         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
390             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
391                 return method;
392
393         mono_stats.inflated_method_count++;
394         mono_stats.generics_metadata_size +=
395                 sizeof (MonoMethodInflated) - sizeof (MonoMethodNormal);
396
397         result = g_new0 (MonoMethodInflated, 1);
398         result->nmethod = *(MonoMethodNormal*)method;
399
400         if (result->nmethod.header)
401                 result->nmethod.header = inflate_generic_header (
402                         result->nmethod.header, context);
403
404         if (klass)
405                 result->nmethod.method.klass = klass;
406         else {
407                 MonoType *declaring = mono_class_inflate_generic_type (
408                         &method->klass->byval_arg, context);
409                 result->nmethod.method.klass = mono_class_from_mono_type (declaring);
410         }
411
412         result->nmethod.method.signature = inflate_generic_signature (
413                 method->klass->image, method->signature, context);
414
415         if (context->gmethod) {
416                 result->context = g_new0 (MonoGenericContext, 1);
417                 result->context->gmethod = context->gmethod;
418                 result->context->ginst = result->nmethod.method.klass->generic_inst;
419
420                 mono_stats.generics_metadata_size += sizeof (MonoGenericContext);
421         } else
422                 result->context = result->nmethod.method.klass->generic_inst->context;
423
424         if (method->signature->is_inflated)
425                 result->declaring = ((MonoMethodInflated *) method)->declaring;
426         else
427                 result->declaring = method;
428
429         return (MonoMethod *) result;
430 }
431
432 /** 
433  * class_compute_field_layout:
434  * @m: pointer to the metadata.
435  * @class: The class to initialize
436  *
437  * Initializes the class->fields.
438  *
439  * Currently we only support AUTO_LAYOUT, and do not even try to do
440  * a good job at it.  This is temporary to get the code for Paolo.
441  */
442 static void
443 class_compute_field_layout (MonoClass *class)
444 {
445         MonoImage *m = class->image; 
446         const int top = class->field.count;
447         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
448         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
449         int i, blittable = TRUE, real_size = 0;
450         guint32 rva;
451         guint32 packing_size = 0;
452         gboolean explicit_size;
453         MonoClassField *field;
454
455         if (class->size_inited)
456                 return;
457
458         if (class->parent) {
459                 if (!class->parent->size_inited)
460                         class_compute_field_layout (class->parent);
461                 class->instance_size += class->parent->instance_size;
462                 class->min_align = class->parent->min_align;
463                 blittable = class->parent->blittable;
464         } else {
465                 class->instance_size = sizeof (MonoObject);
466                 class->min_align = 1;
467         }
468
469         /* Get the real size */
470         explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
471
472         if (explicit_size) {
473                 g_assert ((packing_size & 0xfffffff0) == 0);
474                 class->packing_size = packing_size;
475                 real_size += class->instance_size;
476         }
477
478         if (!top) {
479                 if (explicit_size && real_size) {
480                         class->instance_size = MAX (real_size, class->instance_size);
481                 }
482                 class->size_inited = 1;
483                 return;
484         }
485
486         class->fields = g_new0 (MonoClassField, top);
487
488         /*
489          * Fetch all the field information.
490          */
491         for (i = 0; i < top; i++){
492                 const char *sig;
493                 guint32 cols [MONO_FIELD_SIZE];
494                 int idx = class->field.first + i;
495
496                 field = &class->fields [i];
497                 mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
498                 /* The name is needed for fieldrefs */
499                 field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
500                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
501                 mono_metadata_decode_value (sig, &sig);
502                 /* FIELD signature == 0x06 */
503                 g_assert (*sig == 0x06);
504                 field->type = mono_metadata_parse_field_type (
505                         m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
506                 if (mono_field_is_deleted (field))
507                         continue;
508                 if (class->generic_inst) {
509                         field->type = mono_class_inflate_generic_type (
510                                 field->type, class->generic_inst->context);
511                         field->type->attrs = cols [MONO_FIELD_FLAGS];
512                 }
513
514                 field->parent = class;
515
516                 /* Only do these checks if we still think this type is blittable */
517                 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
518                         if (field->type->byref) {
519                                 blittable = FALSE;
520                         } else {
521                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
522                                 if (!field_class || !field_class->blittable)
523                                         blittable = FALSE;
524                         }
525                 }
526
527                 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
528                         mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
529                         if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
530                                 g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, field->name);
531                 }
532
533                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
534                         mono_metadata_field_info (m, idx, NULL, &rva, NULL);
535                         if (!rva)
536                                 g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
537                         field->data = mono_image_rva_map (class->image, rva);
538                 }
539
540                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
541                         class->enum_basetype = field->type;
542                         class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
543                         blittable = class->element_class->blittable;
544                 }
545
546                 /* The def_value of fields is compute lazily during vtable creation */
547         }
548
549         if (class == mono_defaults.string_class)
550                 blittable = FALSE;
551
552         class->blittable = blittable;
553
554         if (class->enumtype && !class->enum_basetype) {
555                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
556                         G_BREAKPOINT ();
557         }
558         if (explicit_size && real_size) {
559                 class->instance_size = MAX (real_size, class->instance_size);
560         }
561
562         if (class->gen_params)
563                 return;
564
565         mono_class_layout_fields (class);
566 }
567
568 void
569 mono_class_layout_fields (MonoClass *class)
570 {
571         int i;
572         const int top = class->field.count;
573         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
574         guint32 pass, passes, real_size;
575         gboolean gc_aware_layout = FALSE;
576         MonoClassField *field;
577
578         /*
579          * Enable GC aware auto layout: in this mode, reference
580          * fields are grouped together inside objects, increasing collector 
581          * performance.
582          * Requires that all classes whose layout is known to native code be annotated
583          * with [StructLayout (LayoutKind.Sequential)]
584          * Value types have gc_aware_layout disabled by default, as per
585          * what the default is for other runtimes.
586          */
587          /* corlib is missing [StructLayout] directives in many places */
588         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
589                 if (class->image != mono_defaults.corlib &&
590                         class->byval_arg.type != MONO_TYPE_VALUETYPE)
591                         gc_aware_layout = TRUE;
592         }
593
594         /*
595          * Compute field layout and total size (not considering static fields)
596          */
597
598         switch (layout) {
599         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
600         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
601
602                 if (gc_aware_layout)
603                         passes = 2;
604                 else
605                         passes = 1;
606
607                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
608                         passes = 1;
609
610                 if (class->parent)
611                         real_size = class->parent->instance_size;
612                 else
613                         real_size = sizeof (MonoObject);
614
615                 for (pass = 0; pass < passes; ++pass) {
616                         for (i = 0; i < top; i++){
617                                 int size, align;
618                                 field = &class->fields [i];
619
620                                 if (mono_field_is_deleted (field))
621                                         continue;
622                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
623                                         continue;
624
625                                 if (gc_aware_layout) {
626                                         /* 
627                                          * We process fields with reference type in the first pass,
628                                          * and fields with non-reference type in the second pass.
629                                          * We use IS_POINTER instead of IS_REFERENCE because in
630                                          * some internal structures, we store GC_MALLOCed memory
631                                          * in IntPtr fields...
632                                          */
633                                         if (MONO_TYPE_IS_POINTER (field->type)) {
634                                                 if (pass == 1)
635                                                         continue;
636                                         } else {
637                                                 if (pass == 0)
638                                                         continue;
639                                         }
640                                 }
641
642                                 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
643                                         (strcmp (field->name, "$PRIVATE$") == 0)) {
644                                         /* This field is a hack inserted by MCS to empty structures */
645                                         continue;
646                                 }
647
648                                 size = mono_type_size (field->type, &align);
649                         
650                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
651                                 align = class->packing_size ? MIN (class->packing_size, align): align;
652                                 class->min_align = MAX (align, class->min_align);
653                                 field->offset = real_size;
654                                 field->offset += align - 1;
655                                 field->offset &= ~(align - 1);
656                                 real_size = field->offset + size;
657                         }
658
659                         class->instance_size = MAX (real_size, class->instance_size);
660        
661                         if (class->instance_size & (class->min_align - 1)) {
662                                 class->instance_size += class->min_align - 1;
663                                 class->instance_size &= ~(class->min_align - 1);
664                         }
665                 }
666                 break;
667         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
668                 real_size = 0;
669                 for (i = 0; i < top; i++) {
670                         int size, align;
671                         field = &class->fields [i];
672
673                         /*
674                          * There must be info about all the fields in a type if it
675                          * uses explicit layout.
676                          */
677
678                         if (mono_field_is_deleted (field))
679                                 continue;
680                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
681                                 continue;
682
683                         size = mono_type_size (field->type, &align);
684                         
685                         /*
686                          * When we get here, field->offset is already set by the
687                          * loader (for either runtime fields or fields loaded from metadata).
688                          * The offset is from the start of the object: this works for both
689                          * classes and valuetypes.
690                          */
691                         field->offset += sizeof (MonoObject);
692
693                         /*
694                          * Calc max size.
695                          */
696                         real_size = MAX (real_size, size + field->offset);
697                 }
698                 class->instance_size = MAX (real_size, class->instance_size);
699                 break;
700         }
701
702         class->size_inited = 1;
703
704         /*
705          * Compute static field layout and size
706          */
707         for (i = 0; i < top; i++){
708                 int size, align;
709                 field = &class->fields [i];
710                         
711                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
712                         continue;
713                 if (mono_field_is_deleted (field))
714                         continue;
715                         
716                 size = mono_type_size (field->type, &align);
717                 field->offset = class->class_size;
718                 field->offset += align - 1;
719                 field->offset &= ~(align - 1);
720                 class->class_size = field->offset + size;
721         }
722 }
723
724 static void
725 init_properties (MonoClass *class)
726 {
727         guint startm, endm, i, j;
728         guint32 cols [MONO_PROPERTY_SIZE];
729         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
730         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
731
732         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
733         class->property.count = class->property.last - class->property.first;
734
735         class->properties = g_new0 (MonoProperty, class->property.count);
736         for (i = class->property.first; i < class->property.last; ++i) {
737                 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
738                 class->properties [i - class->property.first].parent = class;
739                 class->properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
740                 class->properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
741
742                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
743                 for (j = startm; j < endm; ++j) {
744                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
745                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
746                         case METHOD_SEMANTIC_SETTER:
747                                 class->properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
748                                 break;
749                         case METHOD_SEMANTIC_GETTER:
750                                 class->properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
751                                 break;
752                         default:
753                                 break;
754                         }
755                 }
756         }
757 }
758
759 static void
760 init_events (MonoClass *class)
761 {
762         guint startm, endm, i, j;
763         guint32 cols [MONO_EVENT_SIZE];
764         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
765         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
766
767         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
768         class->event.count = class->event.last - class->event.first;
769
770         class->events = g_new0 (MonoEvent, class->event.count);
771         for (i = class->event.first; i < class->event.last; ++i) {
772                 mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
773                 class->events [i - class->event.first].parent = class;
774                 class->events [i - class->event.first].attrs = cols [MONO_EVENT_FLAGS];
775                 class->events [i - class->event.first].name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
776
777                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
778                 for (j = startm; j < endm; ++j) {
779                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
780                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
781                         case METHOD_SEMANTIC_ADD_ON:
782                                 class->events [i - class->event.first].add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
783                                 break;
784                         case METHOD_SEMANTIC_REMOVE_ON:
785                                 class->events [i - class->event.first].remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
786                                 break;
787                         case METHOD_SEMANTIC_FIRE:
788                                 class->events [i - class->event.first].raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
789                                 break;
790                         case METHOD_SEMANTIC_OTHER: /* don't care for now */
791                         default:
792                                 break;
793                         }
794                 }
795         }
796 }
797
798 static guint
799 mono_get_unique_iid (MonoClass *class)
800 {
801         static GHashTable *iid_hash = NULL;
802         static guint iid = 0;
803
804         char *str;
805         gpointer value;
806         
807         g_assert (MONO_CLASS_IS_INTERFACE (class));
808
809         mono_loader_lock ();
810
811         if (!iid_hash)
812                 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
813
814         str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
815
816         if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
817                 mono_loader_unlock ();
818                 g_free (str);
819                 return (guint)value;
820         } else {
821                 g_hash_table_insert (iid_hash, str, (gpointer)iid);
822                 ++iid;
823         }
824
825         mono_loader_unlock ();
826
827         return iid - 1;
828 }
829
830 static void
831 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
832 {
833         int i;
834         MonoClass *ic;
835         
836         for (i = 0; i < klass->interface_count; i++) {
837                 ic = klass->interfaces [i];
838
839                 if (*res == NULL)
840                         *res = g_ptr_array_new ();
841                 g_ptr_array_add (*res, ic);
842
843                 collect_implemented_interfaces_aux (ic, res);
844         }
845 }
846
847 static inline GPtrArray*
848 collect_implemented_interfaces (MonoClass *klass)
849 {
850         GPtrArray *res = NULL;
851
852         collect_implemented_interfaces_aux (klass, &res);
853         return res;
854 }
855
856 static int
857 setup_interface_offsets (MonoClass *class, int cur_slot)
858 {
859         MonoClass *k, *ic;
860         int i, max_iid;
861         GPtrArray *ifaces;
862
863         /* compute maximum number of slots and maximum interface id */
864         max_iid = 0;
865         for (k = class; k ; k = k->parent) {
866                 for (i = 0; i < k->interface_count; i++) {
867                         ic = k->interfaces [i];
868
869                         if (!ic->inited)
870                                 mono_class_init (ic);
871
872                         if (max_iid < ic->interface_id)
873                                 max_iid = ic->interface_id;
874                 }
875         }
876
877         if (MONO_CLASS_IS_INTERFACE (class)) {
878                 if (max_iid < class->interface_id)
879                         max_iid = class->interface_id;
880         }
881         class->max_interface_id = max_iid;
882         /* compute vtable offset for interfaces */
883         class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
884
885         for (i = 0; i <= max_iid; i++)
886                 class->interface_offsets [i] = -1;
887
888         ifaces = collect_implemented_interfaces (class);
889         if (ifaces) {
890                 for (i = 0; i < ifaces->len; ++i) {
891                         ic = g_ptr_array_index (ifaces, i);
892                         class->interface_offsets [ic->interface_id] = cur_slot;
893                         cur_slot += ic->method.count;
894                 }
895                 g_ptr_array_free (ifaces, TRUE);
896         }
897
898         for (k = class->parent; k ; k = k->parent) {
899                 ifaces = collect_implemented_interfaces (k);
900                 if (ifaces) {
901                         for (i = 0; i < ifaces->len; ++i) {
902                                 ic = g_ptr_array_index (ifaces, i);
903
904                                 if (class->interface_offsets [ic->interface_id] == -1) {
905                                         int io = k->interface_offsets [ic->interface_id];
906
907                                         g_assert (io >= 0);
908
909                                         class->interface_offsets [ic->interface_id] = io;
910                                 }
911                         }
912                         g_ptr_array_free (ifaces, TRUE);
913                 }
914         }
915
916         if (MONO_CLASS_IS_INTERFACE (class))
917                 class->interface_offsets [class->interface_id] = cur_slot;
918
919         return cur_slot;
920 }
921
922 void
923 mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
924 {
925         MonoClass *k, *ic;
926         MonoMethod **vtable;
927         int i, max_vtsize = 0, max_iid, cur_slot = 0;
928         GPtrArray *ifaces;
929         MonoGHashTable *override_map = NULL;
930
931         /* setup_vtable() must be called only once on the type */
932         if (class->interface_offsets) {
933                 g_warning ("vtable already computed in %s.%s", class->name_space, class->name);
934                 return;
935         }
936
937         ifaces = collect_implemented_interfaces (class);
938         if (ifaces) {
939                 for (i = 0; i < ifaces->len; i++) {
940                         MonoClass *ic = g_ptr_array_index (ifaces, i);
941                         max_vtsize += ic->method.count;
942                 }
943                 g_ptr_array_free (ifaces, TRUE);
944         }
945         
946         if (class->parent) {
947                 max_vtsize += class->parent->vtable_size;
948                 cur_slot = class->parent->vtable_size;
949         }
950
951         max_vtsize += class->method.count;
952
953         vtable = alloca (sizeof (gpointer) * max_vtsize);
954         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
955
956         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
957
958         cur_slot = setup_interface_offsets (class, cur_slot);
959         max_iid = class->max_interface_id;
960
961         if (class->parent && class->parent->vtable_size)
962                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
963
964         /* override interface methods */
965         for (i = 0; i < onum; i++) {
966                 MonoMethod *decl = overrides [i*2];
967                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
968                         int dslot;
969                         g_assert (decl->slot != -1);
970                         dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
971                         vtable [dslot] = overrides [i*2 + 1];
972                         vtable [dslot]->slot = dslot;
973                         if (!override_map)
974                                 override_map = mono_g_hash_table_new (NULL, NULL);
975
976                         mono_g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
977                 }
978         }
979
980         for (k = class; k ; k = k->parent) {
981                 int nifaces = 0;
982                 ifaces = collect_implemented_interfaces (k);
983                 if (ifaces)
984                         nifaces = ifaces->len;
985                 for (i = 0; i < nifaces; i++) {
986                         int j, l, io;
987
988                         ic = g_ptr_array_index (ifaces, i);
989                         io = k->interface_offsets [ic->interface_id];
990
991                         g_assert (io >= 0);
992                         g_assert (io <= max_vtsize);
993
994                         if (k == class) {
995                                 for (l = 0; l < ic->method.count; l++) {
996                                         MonoMethod *im = ic->methods [l];                                               
997
998                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
999                                                 continue;
1000
1001                                         for (j = 0; j < class->method.count; ++j) {
1002                                                 MonoMethod *cm = class->methods [j];
1003                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1004                                                     !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
1005                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
1006                                                         continue;
1007                                                 if (!strcmp(cm->name, im->name) && 
1008                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
1009                                                         g_assert (io + l <= max_vtsize);
1010                                                         vtable [io + l] = cm;
1011                                                 }
1012                                         }
1013                                 }
1014                         } else {
1015                                 /* already implemented */
1016                                 if (io >= k->vtable_size)
1017                                         continue;
1018                         }
1019                                 
1020                         for (l = 0; l < ic->method.count; l++) {
1021                                 MonoMethod *im = ic->methods [l];                                               
1022                                 MonoClass *k1;
1023
1024                                 g_assert (io + l <= max_vtsize);
1025
1026                                 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1027                                         continue;
1028                                         
1029                                 for (k1 = class; k1; k1 = k1->parent) {
1030                                         for (j = 0; j < k1->method.count; ++j) {
1031                                                 MonoMethod *cm = k1->methods [j];
1032
1033                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1034                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
1035                                                         continue;
1036                                                 
1037                                                 if (!strcmp(cm->name, im->name) && 
1038                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
1039                                                         g_assert (io + l <= max_vtsize);
1040                                                         vtable [io + l] = cm;
1041                                                         break;
1042                                                 }
1043                                                 
1044                                         }
1045                                         g_assert (io + l <= max_vtsize);
1046                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1047                                                 break;
1048                                 }
1049                         }
1050
1051                         for (l = 0; l < ic->method.count; l++) {
1052                                 MonoMethod *im = ic->methods [l];                                               
1053                                 char *qname, *fqname, *cname, *the_cname;
1054                                 MonoClass *k1, *the_ic;
1055                                 
1056                                 if (vtable [io + l])
1057                                         continue;
1058
1059                                 if (ic->generic_inst) {
1060                                         MonoClass *the_ic = mono_class_from_mono_type (ic->generic_inst->generic_type);
1061                                         the_cname = _mono_type_get_name (&the_ic->byval_arg, FALSE);
1062                                         cname = the_cname;
1063                                 } else {
1064                                         the_cname = NULL;
1065                                         cname = ic->name;
1066                                 }
1067                                         
1068                                 qname = g_strconcat (cname, ".", im->name, NULL);
1069                                 if (ic->name_space && ic->name_space [0])
1070                                         fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
1071                                 else
1072                                         fqname = NULL;
1073
1074                                 for (k1 = class; k1; k1 = k1->parent) {
1075                                         for (j = 0; j < k1->method.count; ++j) {
1076                                                 MonoMethod *cm = k1->methods [j];
1077
1078                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1079                                                         continue;
1080                                         
1081                                                 if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
1082                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
1083                                                         g_assert (io + l <= max_vtsize);
1084                                                         vtable [io + l] = cm;
1085                                                         break;
1086                                                 }
1087                                         }
1088                                 }
1089                                 g_free (the_cname);
1090                                 g_free (qname);
1091                                 g_free (fqname);
1092                         }
1093
1094                         
1095                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
1096                                 for (l = 0; l < ic->method.count; l++) {
1097                                         char *msig;
1098                                         MonoMethod *im = ic->methods [l];
1099                                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
1100                                                         continue;
1101                                         g_assert (io + l <= max_vtsize);
1102
1103                                         /* 
1104                                          * If one of our parents already implements this interface
1105                                          * we can inherit the implementation.
1106                                          */
1107                                         if (!(vtable [io + l])) {
1108                                                 MonoClass *parent = class->parent;
1109
1110                                                 if ((ic->interface_id <= parent->max_interface_id) && 
1111                                                         (parent->interface_offsets [ic->interface_id]) &&
1112                                                         parent->vtable)
1113                                                         vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
1114                                         }
1115
1116                                         if (!(vtable [io + l])) {
1117                                                 for (j = 0; j < onum; ++j) {
1118                                                         g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
1119                                                                  overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
1120                                                 }
1121                                                 msig = mono_signature_get_desc (im->signature, FALSE);
1122                                                 printf ("no implementation for interface method %s.%s::%s(%s) in class %s.%s\n",
1123                                                         ic->name_space, ic->name, im->name, msig, class->name_space, class->name);
1124                                                 g_free (msig);
1125                                                 for (j = 0; j < class->method.count; ++j) {
1126                                                         MonoMethod *cm = class->methods [j];
1127                                                         msig = mono_signature_get_desc (cm->signature, FALSE);
1128                                                         
1129                                                         printf ("METHOD %s(%s)\n", cm->name, msig);
1130                                                         g_free (msig);
1131                                                 }
1132                                                 g_assert_not_reached ();
1133                                         }
1134                                 }
1135                         }
1136                 
1137                         for (l = 0; l < ic->method.count; l++) {
1138                                 MonoMethod *im = vtable [io + l];
1139
1140                                 if (im) {
1141                                         g_assert (io + l <= max_vtsize);
1142                                         if (im->slot < 0) {
1143                                                 /* FIXME: why do we need this ? */
1144                                                 im->slot = io + l;
1145                                                 /* g_assert_not_reached (); */
1146                                         }
1147                                 }
1148                         }
1149                 }
1150                 if (ifaces)
1151                         g_ptr_array_free (ifaces, TRUE);
1152         } 
1153
1154         for (i = 0; i < class->method.count; ++i) {
1155                 MonoMethod *cm;
1156                
1157                 cm = class->methods [i];
1158                 
1159                 /*
1160                  * Non-virtual method have no place in the vtable.
1161                  * This also catches static methods (since they are not virtual).
1162                  */
1163                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1164                         continue;
1165                 
1166                 /*
1167                  * If the method is REUSE_SLOT, we must check in the
1168                  * base class for a method to override.
1169                  */
1170                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
1171                         int slot = -1;
1172                         for (k = class->parent; k ; k = k->parent) {
1173                                 int j;
1174                                 for (j = 0; j < k->method.count; ++j) {
1175                                         MonoMethod *m1 = k->methods [j];
1176                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
1177                                                 continue;
1178                                         if (!strcmp(cm->name, m1->name) && 
1179                                             mono_metadata_signature_equal (cm->signature, m1->signature)) {
1180                                                 slot = k->methods [j]->slot;
1181                                                 g_assert (cm->slot < max_vtsize);
1182                                                 if (!override_map)
1183                                                         override_map = mono_g_hash_table_new (NULL, NULL);
1184                                                 mono_g_hash_table_insert (override_map, m1, cm);
1185                                                 break;
1186                                         }
1187                                 }
1188                                 if (slot >= 0) 
1189                                         break;
1190                         }
1191                         if (slot >= 0)
1192                                 cm->slot = slot;
1193                 }
1194
1195                 if (cm->slot < 0)
1196                         cm->slot = cur_slot++;
1197
1198                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && !cm->signature->generic_param_count)
1199                         vtable [cm->slot] = cm;
1200         }
1201
1202         /* override non interface methods */
1203         for (i = 0; i < onum; i++) {
1204                 MonoMethod *decl = overrides [i*2];
1205                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
1206                         g_assert (decl->slot != -1);
1207                         vtable [decl->slot] = overrides [i*2 + 1];
1208                         overrides [i * 2 + 1]->slot = decl->slot;
1209                         if (!override_map)
1210                                 override_map = mono_g_hash_table_new (NULL, NULL);
1211                         mono_g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
1212                 }
1213         }
1214
1215         /*
1216          * If a method occupies more than one place in the vtable, and it is
1217          * overriden, then change the other occurances too.
1218          */
1219         if (override_map) {
1220                 for (i = 0; i < max_vtsize; ++i)
1221                         if (vtable [i]) {
1222                                 MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
1223                                 if (cm)
1224                                         vtable [i] = cm;
1225                         }
1226
1227                 mono_g_hash_table_destroy (override_map);
1228         }
1229
1230         if (class->generic_inst) {
1231                 MonoClass *gklass = mono_class_from_mono_type (class->generic_inst->generic_type);
1232
1233                 mono_class_init (gklass);
1234                 class->vtable_size = gklass->vtable_size;
1235         } else       
1236                 class->vtable_size = cur_slot;
1237
1238         class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
1239         memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
1240
1241         if (mono_print_vtable) {
1242                 int icount = 0;
1243
1244                 for (i = 0; i <= max_iid; i++)
1245                         if (class->interface_offsets [i] != -1)
1246                                 icount++;
1247
1248                 printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space, 
1249                         class->name, class->vtable_size, icount); 
1250
1251                 for (i = 0; i < class->vtable_size; ++i) {
1252                         MonoMethod *cm;
1253                
1254                         cm = vtable [i];
1255                         if (cm) {
1256                                 printf ("  slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
1257                                         cm->klass->name_space, cm->klass->name,
1258                                         cm->name);
1259                         }
1260                 }
1261
1262
1263                 if (icount) {
1264                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
1265                                 class->name, max_iid);
1266         
1267                         for (i = 0; i < class->interface_count; i++) {
1268                                 ic = class->interfaces [i];
1269                                 printf ("  slot %03d(%03d) %s.%s\n",  
1270                                         class->interface_offsets [ic->interface_id],
1271                                         ic->method.count, ic->name_space, ic->name);
1272                         }
1273
1274                         for (k = class->parent; k ; k = k->parent) {
1275                                 for (i = 0; i < k->interface_count; i++) {
1276                                         ic = k->interfaces [i]; 
1277                                         printf ("  slot %03d(%03d) %s.%s\n", 
1278                                                 class->interface_offsets [ic->interface_id],
1279                                                 ic->method.count, ic->name_space, ic->name);
1280                                 }
1281                         }
1282                 }
1283         }
1284 }
1285
1286 /**
1287  * mono_class_init:
1288  * @class: the class to initialize
1289  *
1290  * compute the instance_size, class_size and other infos that cannot be 
1291  * computed at mono_class_get() time. Also compute a generic vtable and 
1292  * the method slot numbers. We use this infos later to create a domain
1293  * specific vtable.  
1294  */
1295 void
1296 mono_class_init (MonoClass *class)
1297 {
1298         int i;
1299         static MonoMethod *default_ghc = NULL;
1300         static MonoMethod *default_finalize = NULL;
1301         static int finalize_slot = -1;
1302         static int ghc_slot = -1;
1303         MonoMethod **overrides;
1304         int onum = 0;
1305
1306         g_assert (class);
1307
1308         if (class->inited)
1309                 return;
1310
1311         /*g_print ("Init class %s\n", class->name);*/
1312
1313         /* We do everything inside the lock to prevent races */
1314         mono_loader_lock ();
1315
1316         if (class->inited) {
1317                 mono_loader_unlock ();
1318                 /* Somebody might have gotten in before us */
1319                 return;
1320         }
1321
1322         if (class->init_pending) {
1323                 /* this indicates a cyclic dependency */
1324                 g_error ("pending init %s.%s\n", class->name_space, class->name);
1325         }
1326
1327         class->init_pending = 1;
1328
1329         if (mono_debugger_start_class_init_func)
1330                 mono_debugger_start_class_init_func (class);
1331
1332         mono_stats.initialized_class_count++;
1333
1334         if (class->generic_inst && !class->generic_inst->is_dynamic) {
1335                 MonoGenericInst *ginst = class->generic_inst;
1336                 MonoClass *gklass;
1337                 GList *list;
1338
1339                 gklass = mono_class_from_mono_type (ginst->generic_type);
1340                 mono_class_init (gklass);
1341
1342                 if (ginst->parent)
1343                         class->parent = mono_class_from_mono_type (ginst->parent);
1344                 else
1345                         class->parent = gklass->parent;
1346
1347                 mono_class_setup_parent (class, class->parent);
1348
1349                 if (MONO_CLASS_IS_INTERFACE (class))
1350                         class->interface_id = mono_get_unique_iid (class);
1351
1352                 class->method = gklass->method;
1353                 class->methods = g_new0 (MonoMethod *, class->method.count);
1354
1355                 for (i = 0; i < class->method.count; i++)
1356                         class->methods [i] = mono_class_inflate_generic_method (
1357                                 gklass->methods [i], ginst->context, ginst->klass);
1358
1359                 class->field = gklass->field;
1360                 class->fields = g_new0 (MonoClassField, class->field.count);
1361
1362                 for (i = 0; i < class->field.count; i++) {
1363                         MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
1364                         ifield->generic_type = gklass->fields [i].type;
1365
1366                         class->fields [i] = gklass->fields [i];
1367                         class->fields [i].generic_info = ifield;
1368                         class->fields [i].parent = class;
1369                         class->fields [i].type = mono_class_inflate_generic_type (
1370                                 class->fields [i].type, ginst->context);
1371                 }
1372
1373                 class->property = gklass->property;
1374                 class->properties = g_new0 (MonoProperty, class->property.count);
1375
1376                 for (i = 0; i < class->property.count; i++) {
1377                         MonoProperty *prop = &class->properties [i];
1378
1379                         *prop = gklass->properties [i];
1380
1381                         if (prop->get)
1382                                 prop->get = mono_class_inflate_generic_method (
1383                                         prop->get, ginst->context, ginst->klass);
1384                         if (prop->set)
1385                                 prop->set = mono_class_inflate_generic_method (
1386                                         prop->set, ginst->context, ginst->klass);
1387
1388                         prop->parent = class;
1389                 }
1390
1391                 class->interface_count = gklass->interface_count;
1392                 class->interfaces = g_new0 (MonoClass *, class->interface_count);
1393                 for (i = 0; i < class->interface_count; i++) {
1394                         MonoType *it = &gklass->interfaces [i]->byval_arg;
1395                         MonoType *inflated = mono_class_inflate_generic_type (
1396                                 it, ginst->context);
1397                         class->interfaces [i] = mono_class_from_mono_type (inflated);
1398                         mono_class_init (class->interfaces [i]);
1399                 }
1400
1401                 for (list = gklass->nested_classes; list; list = list->next)
1402                         class->nested_classes = g_list_append (
1403                                 class->nested_classes, list->data);
1404         }
1405
1406         if (class->parent && !class->parent->inited)
1407                 mono_class_init (class->parent);
1408
1409         /*
1410          * Computes the size used by the fields, and their locations
1411          */
1412         if (!class->size_inited)
1413                 class_compute_field_layout (class);
1414
1415         /* initialize method pointers */
1416         if (class->rank) {
1417                 MonoMethod *ctor;
1418                 MonoMethodSignature *sig;
1419                 class->method.count = class->rank > 1? 2: 1;
1420                 sig = mono_metadata_signature_alloc (class->image, class->rank);
1421                 sig->ret = &mono_defaults.void_class->byval_arg;
1422                 sig->pinvoke = TRUE;
1423                 for (i = 0; i < class->rank; ++i)
1424                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
1425
1426                 ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
1427                 ctor->klass = class;
1428                 ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1429                 ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1430                 ctor->signature = sig;
1431                 ctor->name = ".ctor";
1432                 ctor->slot = -1;
1433                 class->methods = g_new (MonoMethod*, class->method.count);
1434                 class->methods [0] = ctor;
1435                 if (class->rank > 1) {
1436                         sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
1437                         sig->ret = &mono_defaults.void_class->byval_arg;
1438                         sig->pinvoke = TRUE;
1439                         for (i = 0; i < class->rank * 2; ++i)
1440                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
1441
1442                         ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
1443                         ctor->klass = class;
1444                         ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1445                         ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1446                         ctor->signature = sig;
1447                         ctor->name = ".ctor";
1448                         ctor->slot = -1;
1449                         class->methods [1] = ctor;
1450                 }
1451         } else {
1452                 if (!class->generic_inst && !class->methods) {
1453                         class->methods = g_new (MonoMethod*, class->method.count);
1454                         for (i = 0; i < class->method.count; ++i) {
1455                                 class->methods [i] = mono_get_method (class->image,
1456                                                                       MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
1457                         }
1458                 }
1459         }
1460
1461         if (!class->generic_inst) {
1462                 init_properties (class);
1463                 init_events (class);
1464
1465                 i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
1466                 while (i) {
1467                         MonoClass* nclass;
1468                         guint32 cols [MONO_NESTED_CLASS_SIZE];
1469                         mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
1470                         nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
1471                         class->nested_classes = g_list_prepend (class->nested_classes, nclass);
1472
1473                         i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
1474                 }
1475         }
1476
1477         mono_class_setup_supertypes (class);
1478
1479         if (MONO_CLASS_IS_INTERFACE (class)) {
1480                 for (i = 0; i < class->method.count; ++i)
1481                         class->methods [i]->slot = i;
1482                 class->init_pending = 0;
1483                 class->inited = 1;
1484                 /* 
1485                  * class->interface_offsets is needed for the castclass/isinst code, so
1486                  * we have to setup them for interfaces, too.
1487                  */
1488                 setup_interface_offsets (class, 0);
1489                 mono_loader_unlock ();
1490
1491                 if (mono_debugger_class_init_func)
1492                         mono_debugger_class_init_func (class);
1493
1494                 return;
1495         }
1496
1497         overrides = mono_class_get_overrides (class->image, class->type_token, &onum);  
1498         mono_class_setup_vtable (class, overrides, onum);
1499         g_free (overrides);
1500
1501         class->inited = 1;
1502         class->init_pending = 0;
1503
1504         if (!default_ghc) {
1505                 if (class == mono_defaults.object_class) { 
1506                        
1507                         for (i = 0; i < class->vtable_size; ++i) {
1508                                 MonoMethod *cm = class->vtable [i];
1509                
1510                                 if (!strcmp (cm->name, "GetHashCode")) {
1511                                         ghc_slot = i;
1512                                         break;
1513                                 }
1514                         }
1515
1516                         g_assert (ghc_slot > 0);
1517
1518                         default_ghc = class->vtable [ghc_slot];
1519                 }
1520         }
1521         
1522         class->ghcimpl = 1;
1523         if (class->parent) { 
1524
1525                 if (class->vtable [ghc_slot] == default_ghc) {
1526                         class->ghcimpl = 0;
1527                 }
1528         }
1529
1530         if (!default_finalize) {
1531                 if (class == mono_defaults.object_class) { 
1532                        
1533                         for (i = 0; i < class->vtable_size; ++i) {
1534                                 MonoMethod *cm = class->vtable [i];
1535                
1536                                 if (!strcmp (cm->name, "Finalize")) {
1537                                         finalize_slot = i;
1538                                         break;
1539                                 }
1540                         }
1541
1542                         g_assert (finalize_slot > 0);
1543
1544                         default_finalize = class->vtable [finalize_slot];
1545                 }
1546         }
1547
1548         /* Object::Finalize should have empty implemenatation */
1549         class->has_finalize = 0;
1550         if (class->parent) { 
1551                 if (class->vtable [finalize_slot] != default_finalize)
1552                         class->has_finalize = 1;
1553         }
1554
1555         mono_loader_unlock ();
1556
1557         if (mono_debugger_class_init_func)
1558                 mono_debugger_class_init_func (class);
1559 }
1560
1561 void
1562 mono_class_setup_mono_type (MonoClass *class)
1563 {
1564         const char *name = class->name;
1565         const char *nspace = class->name_space;
1566
1567         if (MONO_CLASS_IS_INTERFACE (class))
1568                 class->interface_id = mono_get_unique_iid (class);
1569
1570         class->this_arg.byref = 1;
1571         class->this_arg.data.klass = class;
1572         class->this_arg.type = MONO_TYPE_CLASS;
1573         class->byval_arg.data.klass = class;
1574         class->byval_arg.type = MONO_TYPE_CLASS;
1575
1576         if (!strcmp (nspace, "System")) {
1577                 if (!strcmp (name, "ValueType")) {
1578                         /*
1579                          * do not set the valuetype bit for System.ValueType.
1580                          * class->valuetype = 1;
1581                          */
1582                         class->blittable = TRUE;
1583                 } else if (!strcmp (name, "Enum")) {
1584                         /*
1585                          * do not set the valuetype bit for System.Enum.
1586                          * class->valuetype = 1;
1587                          */
1588                         class->valuetype = 0;
1589                         class->enumtype = 0;
1590                 } else if (!strcmp (name, "Object")) {
1591                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
1592                 } else if (!strcmp (name, "String")) {
1593                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
1594                 } else if (!strcmp (name, "TypedReference")) {
1595                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
1596                 }
1597         }
1598         
1599         if (class->valuetype) {
1600                 int t = MONO_TYPE_VALUETYPE;
1601                 if (!strcmp (nspace, "System")) {
1602                         switch (*name) {
1603                         case 'B':
1604                                 if (!strcmp (name, "Boolean")) {
1605                                         t = MONO_TYPE_BOOLEAN;
1606                                 } else if (!strcmp(name, "Byte")) {
1607                                         t = MONO_TYPE_U1;
1608                                         class->blittable = TRUE;                                                
1609                                 }
1610                                 break;
1611                         case 'C':
1612                                 if (!strcmp (name, "Char")) {
1613                                         t = MONO_TYPE_CHAR;
1614                                 }
1615                                 break;
1616                         case 'D':
1617                                 if (!strcmp (name, "Double")) {
1618                                         t = MONO_TYPE_R8;
1619                                         class->blittable = TRUE;                                                
1620                                 }
1621                                 break;
1622                         case 'I':
1623                                 if (!strcmp (name, "Int32")) {
1624                                         t = MONO_TYPE_I4;
1625                                         class->blittable = TRUE;
1626                                 } else if (!strcmp(name, "Int16")) {
1627                                         t = MONO_TYPE_I2;
1628                                         class->blittable = TRUE;
1629                                 } else if (!strcmp(name, "Int64")) {
1630                                         t = MONO_TYPE_I8;
1631                                         class->blittable = TRUE;
1632                                 } else if (!strcmp(name, "IntPtr")) {
1633                                         t = MONO_TYPE_I;
1634                                         class->blittable = TRUE;
1635                                 }
1636                                 break;
1637                         case 'S':
1638                                 if (!strcmp (name, "Single")) {
1639                                         t = MONO_TYPE_R4;
1640                                         class->blittable = TRUE;                                                
1641                                 } else if (!strcmp(name, "SByte")) {
1642                                         t = MONO_TYPE_I1;
1643                                         class->blittable = TRUE;
1644                                 }
1645                                 break;
1646                         case 'U':
1647                                 if (!strcmp (name, "UInt32")) {
1648                                         t = MONO_TYPE_U4;
1649                                         class->blittable = TRUE;
1650                                 } else if (!strcmp(name, "UInt16")) {
1651                                         t = MONO_TYPE_U2;
1652                                         class->blittable = TRUE;
1653                                 } else if (!strcmp(name, "UInt64")) {
1654                                         t = MONO_TYPE_U8;
1655                                         class->blittable = TRUE;
1656                                 } else if (!strcmp(name, "UIntPtr")) {
1657                                         t = MONO_TYPE_U;
1658                                         class->blittable = TRUE;
1659                                 }
1660                                 break;
1661                         case 'T':
1662                                 if (!strcmp (name, "TypedReference")) {
1663                                         t = MONO_TYPE_TYPEDBYREF;
1664                                         class->blittable = TRUE;
1665                                 }
1666                                 break;
1667                         case 'V':
1668                                 if (!strcmp (name, "Void")) {
1669                                         t = MONO_TYPE_VOID;
1670                                 }
1671                                 break;
1672                         default:
1673                                 break;
1674                         }
1675                 }
1676                 class->this_arg.type = class->byval_arg.type = t;
1677         }
1678 }
1679
1680 void
1681 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
1682 {
1683         gboolean system_namespace;
1684
1685         system_namespace = !strcmp (class->name_space, "System");
1686
1687         /* if root of the hierarchy */
1688         if (system_namespace && !strcmp (class->name, "Object")) {
1689                 class->parent = NULL;
1690                 class->instance_size = sizeof (MonoObject);
1691                 return;
1692         }
1693         if (!strcmp (class->name, "<Module>")) {
1694                 class->parent = NULL;
1695                 class->instance_size = 0;
1696                 return;
1697         }
1698
1699         if (!MONO_CLASS_IS_INTERFACE (class)) {
1700                 class->parent = parent;
1701
1702                 if (!parent)
1703                         g_assert_not_reached (); /* FIXME */
1704
1705                 if (parent->generic_inst && !parent->name) {
1706                         /*
1707                          * If the parent is a generic instance, we may get
1708                          * called before it is fully initialized, especially
1709                          * before it has its name.
1710                          */
1711                         return;
1712                 }
1713
1714                 class->marshalbyref = parent->marshalbyref;
1715                 class->contextbound  = parent->contextbound;
1716                 class->delegate  = parent->delegate;
1717                 
1718                 if (system_namespace) {
1719                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
1720                                 class->marshalbyref = 1;
1721
1722                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
1723                                 class->contextbound  = 1;
1724
1725                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
1726                                 class->delegate  = 1;
1727                 }
1728
1729                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
1730                                                 (strcmp (class->parent->name_space, "System") == 0)))
1731                         class->valuetype = 1;
1732                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
1733                         class->valuetype = class->enumtype = 1;
1734                 }
1735                 /*class->enumtype = class->parent->enumtype; */
1736                 mono_class_setup_supertypes (class);
1737         } else {
1738                 class->parent = NULL;
1739         }
1740
1741 }
1742
1743 void
1744 mono_class_setup_supertypes (MonoClass *class)
1745 {
1746         MonoClass *k;
1747         int ms, i;
1748
1749         if (class->supertypes)
1750                 return;
1751
1752         class->idepth = 0;
1753         for (k = class; k ; k = k->parent) {
1754                 class->idepth++;
1755         }
1756
1757         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
1758         class->supertypes = g_new0 (MonoClass *, ms);
1759
1760         if (class->parent) {
1761                 for (i = class->idepth, k = class; k ; k = k->parent)
1762                         class->supertypes [--i] = k;
1763         } else {
1764                 class->supertypes [0] = class;
1765         }
1766 }       
1767
1768 /**
1769  * @image: context where the image is created
1770  * @type_token:  typedef token
1771  */
1772 static MonoClass *
1773 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
1774 {
1775         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
1776         MonoClass *class, *parent = NULL;
1777         guint32 cols [MONO_TYPEDEF_SIZE];
1778         guint32 cols_next [MONO_TYPEDEF_SIZE];
1779         guint tidx = mono_metadata_token_index (type_token);
1780         const char *name, *nspace;
1781         guint icount = 0; 
1782         MonoClass **interfaces;
1783
1784         mono_loader_lock ();
1785
1786         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
1787                 mono_loader_unlock ();
1788                 return class;
1789         }
1790
1791         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
1792
1793         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
1794         
1795         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1796         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1797
1798         class = g_malloc0 (sizeof (MonoClass));
1799
1800         class->name = name;
1801         class->name_space = nspace;
1802
1803         class->image = image;
1804         class->type_token = type_token;
1805         class->flags = cols [MONO_TYPEDEF_FLAGS];
1806
1807         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
1808
1809         if (cols [MONO_TYPEDEF_EXTENDS])
1810                 parent = mono_class_get (image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]));
1811         interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount);
1812
1813         class->interfaces = interfaces;
1814         class->interface_count = icount;
1815
1816         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
1817                 class->unicode = 1;
1818         /* fixme: maybe we must set this on windows 
1819         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
1820                 class->unicode = 1;
1821         */
1822
1823         class->cast_class = class->element_class = class;
1824
1825         /*g_print ("Load class %s\n", name);*/
1826
1827         mono_class_setup_parent (class, parent);
1828
1829         mono_class_setup_mono_type (class);
1830
1831         /*
1832          * Compute the field and method lists
1833          */
1834         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
1835         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
1836
1837         if (tt->rows > tidx){           
1838                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
1839                 class->field.last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
1840                 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
1841         } else {
1842                 class->field.last  = image->tables [MONO_TABLE_FIELD].rows;
1843                 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
1844         }
1845
1846         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
1847             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
1848                 class->field.count = class->field.last - class->field.first;
1849         else
1850                 class->field.count = 0;
1851
1852         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
1853                 class->method.count = class->method.last - class->method.first;
1854         else
1855                 class->method.count = 0;
1856
1857         /* reserve space to store vector pointer in arrays */
1858         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
1859                 class->instance_size += 2 * sizeof (gpointer);
1860                 g_assert (class->field.count == 0);
1861         }
1862
1863         if (class->enumtype)
1864                 class_compute_field_layout (class);
1865
1866         if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
1867                 class->nested_in = mono_class_create_from_typedef (image, type_token);
1868
1869         class->gen_params = mono_metadata_load_generic_params (image, class->type_token, &icount);
1870         class->num_gen_params = icount;
1871
1872         mono_loader_unlock ();
1873
1874         return class;
1875 }
1876
1877 MonoClass*
1878 mono_class_create_generic (MonoGenericInst *ginst)
1879 {
1880         MonoClass *klass, *gklass;
1881
1882         if (!ginst->klass)
1883                 ginst->klass = g_malloc0 (sizeof (MonoClass));
1884         klass = ginst->klass;
1885
1886         gklass = mono_class_from_mono_type (ginst->generic_type);
1887
1888         klass->nested_in = gklass->nested_in;
1889
1890         klass->name = gklass->name;
1891         klass->name_space = gklass->name_space;
1892         klass->image = gklass->image;
1893         klass->flags = gklass->flags;
1894
1895         klass->generic_inst = ginst;
1896
1897         klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
1898         klass->this_arg.data.generic_inst = klass->byval_arg.data.generic_inst = ginst;
1899         klass->this_arg.byref = TRUE;
1900
1901         klass->cast_class = klass->element_class = klass;
1902
1903         if (ginst->is_dynamic) {
1904                 klass->instance_size = gklass->instance_size;
1905                 klass->class_size = gklass->class_size;
1906                 klass->size_inited = 1;
1907
1908                 klass->valuetype = gklass->valuetype;
1909         }
1910
1911         return klass;
1912 }
1913
1914 MonoClass *
1915 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
1916 {
1917         MonoClass *klass, **ptr;
1918         int count, pos, i;
1919
1920         if (param->pklass)
1921                 return param->pklass;
1922
1923         klass = param->pklass = g_new0 (MonoClass, 1);
1924
1925         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
1926                 ;
1927
1928         pos = 0;
1929         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
1930                 klass->parent = param->constraints [0];
1931                 pos++;
1932         }
1933
1934         if (count - pos > 0) {
1935                 klass->interface_count = count - pos;
1936                 klass->interfaces = g_new0 (MonoClass *, count - pos);
1937                 for (i = pos; i < count; i++)
1938                         klass->interfaces [i - pos] = param->constraints [i];
1939         }
1940
1941         g_assert (param->name);
1942
1943         klass->name = param->name;
1944         klass->name_space = "";
1945         klass->image = image;
1946         klass->cast_class = klass->element_class = klass;
1947         klass->enum_basetype = &klass->element_class->byval_arg;
1948         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
1949
1950         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
1951         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
1952         klass->this_arg.byref = TRUE;
1953
1954         mono_class_init (klass);
1955
1956         return klass;
1957 }
1958
1959 static MonoClass *
1960 my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
1961 {
1962         MonoClass *klass;
1963
1964         if (param->pklass)
1965                 return param->pklass;
1966
1967         klass = g_new0 (MonoClass, 1);
1968
1969         if (param->name)
1970                 klass->name = param->name;
1971         else
1972                 klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
1973         klass->name_space = "";
1974         klass->image = mono_defaults.corlib;
1975         klass->cast_class = klass->element_class = klass;
1976         klass->enum_basetype = &klass->element_class->byval_arg;
1977         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
1978
1979         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
1980         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
1981         klass->this_arg.byref = TRUE;
1982
1983         mono_class_init (klass);
1984
1985         return klass;
1986 }
1987
1988 MonoClass *
1989 mono_ptr_class_get (MonoType *type)
1990 {
1991         MonoClass *result;
1992         MonoClass *el_class;
1993         static GHashTable *ptr_hash = NULL;
1994
1995         mono_loader_lock ();
1996
1997         if (!ptr_hash)
1998                 ptr_hash = g_hash_table_new (NULL, NULL);
1999         el_class = mono_class_from_mono_type (type);
2000         if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
2001                 mono_loader_unlock ();
2002                 return result;
2003         }
2004         result = g_new0 (MonoClass, 1);
2005
2006         result->parent = NULL; /* no parent for PTR types */
2007         result->name = "System";
2008         result->name_space = "MonoPtrFakeClass";
2009         result->image = el_class->image;
2010         result->inited = TRUE;
2011         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
2012         /* Can pointers get boxed? */
2013         result->instance_size = sizeof (gpointer);
2014         result->cast_class = result->element_class = el_class;
2015         result->enum_basetype = &result->element_class->byval_arg;
2016         result->blittable = TRUE;
2017
2018         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
2019         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
2020         result->this_arg.byref = TRUE;
2021
2022         mono_class_setup_supertypes (result);
2023
2024         g_hash_table_insert (ptr_hash, el_class, result);
2025
2026         mono_loader_unlock ();
2027
2028         return result;
2029 }
2030
2031 static MonoClass *
2032 mono_fnptr_class_get (MonoMethodSignature *sig)
2033 {
2034         MonoClass *result;
2035         static GHashTable *ptr_hash = NULL;
2036
2037         mono_loader_lock ();
2038
2039         if (!ptr_hash)
2040                 ptr_hash = g_hash_table_new (NULL, NULL);
2041         
2042         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
2043                 mono_loader_unlock ();
2044                 return result;
2045         }
2046         result = g_new0 (MonoClass, 1);
2047
2048         result->parent = NULL; /* no parent for PTR types */
2049         result->name = "System";
2050         result->name_space = "MonoFNPtrFakeClass";
2051         result->image = NULL; /* need to fix... */
2052         result->inited = TRUE;
2053         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
2054         /* Can pointers get boxed? */
2055         result->instance_size = sizeof (gpointer);
2056         result->cast_class = result->element_class = result;
2057         result->blittable = TRUE;
2058
2059         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
2060         result->this_arg.data.method = result->byval_arg.data.method = sig;
2061         result->this_arg.byref = TRUE;
2062         result->enum_basetype = &result->element_class->byval_arg;
2063         result->blittable = TRUE;
2064
2065         mono_class_setup_supertypes (result);
2066
2067         g_hash_table_insert (ptr_hash, sig, result);
2068
2069         mono_loader_unlock ();
2070
2071         return result;
2072 }
2073
2074 MonoClass *
2075 mono_class_from_mono_type (MonoType *type)
2076 {
2077         switch (type->type) {
2078         case MONO_TYPE_OBJECT:
2079                 return type->data.klass? type->data.klass: mono_defaults.object_class;
2080         case MONO_TYPE_VOID:
2081                 return type->data.klass? type->data.klass: mono_defaults.void_class;
2082         case MONO_TYPE_BOOLEAN:
2083                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
2084         case MONO_TYPE_CHAR:
2085                 return type->data.klass? type->data.klass: mono_defaults.char_class;
2086         case MONO_TYPE_I1:
2087                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
2088         case MONO_TYPE_U1:
2089                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
2090         case MONO_TYPE_I2:
2091                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
2092         case MONO_TYPE_U2:
2093                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
2094         case MONO_TYPE_I4:
2095                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
2096         case MONO_TYPE_U4:
2097                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
2098         case MONO_TYPE_I:
2099                 return type->data.klass? type->data.klass: mono_defaults.int_class;
2100         case MONO_TYPE_U:
2101                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
2102         case MONO_TYPE_I8:
2103                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
2104         case MONO_TYPE_U8:
2105                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
2106         case MONO_TYPE_R4:
2107                 return type->data.klass? type->data.klass: mono_defaults.single_class;
2108         case MONO_TYPE_R8:
2109                 return type->data.klass? type->data.klass: mono_defaults.double_class;
2110         case MONO_TYPE_STRING:
2111                 return type->data.klass? type->data.klass: mono_defaults.string_class;
2112         case MONO_TYPE_TYPEDBYREF:
2113                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
2114         case MONO_TYPE_ARRAY:
2115                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
2116         case MONO_TYPE_PTR:
2117                 return mono_ptr_class_get (type->data.type);
2118         case MONO_TYPE_FNPTR:
2119                 return mono_fnptr_class_get (type->data.method);
2120         case MONO_TYPE_SZARRAY:
2121                 return mono_array_class_get (type->data.klass, 1);
2122         case MONO_TYPE_CLASS:
2123         case MONO_TYPE_VALUETYPE:
2124                 return type->data.klass;
2125         case MONO_TYPE_GENERICINST:
2126                 g_assert (type->data.generic_inst->klass);
2127                 return type->data.generic_inst->klass;
2128         case MONO_TYPE_VAR:
2129                 return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
2130         case MONO_TYPE_MVAR:
2131                 return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
2132         default:
2133                 g_warning ("implement me 0x%02x\n", type->type);
2134                 g_assert_not_reached ();
2135         }
2136         
2137         return NULL;
2138 }
2139
2140 /**
2141  * @image: context where the image is created
2142  * @type_spec:  typespec token
2143  */
2144 static MonoClass *
2145 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
2146                                  MonoGenericContext *context)
2147 {
2148         MonoType *type, *inflated;
2149         MonoClass *class;
2150
2151         type = mono_type_create_from_typespec (image, type_spec);
2152
2153         switch (type->type) {
2154         case MONO_TYPE_ARRAY:
2155                 class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
2156                 break;
2157         case MONO_TYPE_SZARRAY:
2158                 class = mono_array_class_get (type->data.klass, 1);
2159                 break;
2160         case MONO_TYPE_PTR:
2161                 class = mono_ptr_class_get (type->data.type);
2162                 break;
2163         case MONO_TYPE_GENERICINST:
2164                 g_assert (type->data.generic_inst->klass);
2165                 class = type->data.generic_inst->klass;
2166                 break;
2167         default:
2168                 /* it seems any type can be stored in TypeSpec as well */
2169                 class = mono_class_from_mono_type (type);
2170                 break;
2171         }
2172
2173         if (!class || !context)
2174                 return class;
2175
2176         inflated = mono_class_inflate_generic_type (&class->byval_arg, context);
2177
2178         return mono_class_from_mono_type (inflated);
2179 }
2180
2181 /**
2182  * mono_bounded_array_class_get:
2183  * @element_class: element class 
2184  * @rank: the dimension of the array class
2185  * @bounded: whenever the array has non-zero bounds
2186  *
2187  * Returns: a class object describing the array with element type @element_type and 
2188  * dimension @rank. 
2189  */
2190 MonoClass *
2191 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
2192 {
2193         MonoImage *image;
2194         MonoClass *class;
2195         MonoClass *parent = NULL;
2196         GSList *list, *rootlist;
2197         int nsize;
2198         char *name;
2199         gboolean corlib_type = FALSE;
2200
2201         g_assert (rank <= 255);
2202
2203         if (rank > 1)
2204                 /* bounded only matters for one-dimensional arrays */
2205                 bounded = FALSE;
2206
2207         image = eclass->image;
2208
2209         mono_loader_lock ();
2210
2211         if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
2212                 for (; list; list = list->next) {
2213                         class = list->data;
2214                         if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
2215                                 mono_loader_unlock ();
2216                                 return class;
2217                         }
2218                 }
2219         }
2220
2221         /* for the building corlib use System.Array from it */
2222         if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
2223                 parent = mono_class_from_name (image, "System", "Array");
2224                 corlib_type = TRUE;
2225         } else {
2226                 parent = mono_defaults.array_class;
2227                 if (!parent->inited)
2228                         mono_class_init (parent);
2229         }
2230
2231         class = g_malloc0 (sizeof (MonoClass));
2232
2233         class->image = image;
2234         class->name_space = eclass->name_space;
2235         nsize = strlen (eclass->name);
2236         name = g_malloc (nsize + 2 + rank);
2237         memcpy (name, eclass->name, nsize);
2238         name [nsize] = '[';
2239         if (rank > 1)
2240                 memset (name + nsize + 1, ',', rank - 1);
2241         name [nsize + rank] = ']';
2242         name [nsize + rank + 1] = 0;
2243         class->name = name;
2244         class->type_token = 0;
2245         /* all arrays are marked serializable and sealed, bug #42779 */
2246         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
2247                 (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
2248         class->parent = parent;
2249         class->instance_size = mono_class_instance_size (class->parent);
2250         class->class_size = 0;
2251         mono_class_setup_supertypes (class);
2252
2253         class->rank = rank;
2254         
2255         if (eclass->enumtype)
2256                 class->cast_class = eclass->element_class;
2257         else
2258                 class->cast_class = eclass;
2259
2260         class->element_class = eclass;
2261
2262         if ((rank > 1) || bounded) {
2263                 MonoArrayType *at = g_new0 (MonoArrayType, 1);
2264                 class->byval_arg.type = MONO_TYPE_ARRAY;
2265                 class->byval_arg.data.array = at;
2266                 at->eklass = eclass;
2267                 at->rank = rank;
2268                 /* FIXME: complete.... */
2269         } else {
2270                 class->byval_arg.type = MONO_TYPE_SZARRAY;
2271                 class->byval_arg.data.klass = eclass;
2272         }
2273         class->this_arg = class->byval_arg;
2274         class->this_arg.byref = 1;
2275         if (corlib_type) {
2276                 class->inited = 1;
2277         }
2278
2279         list = g_slist_append (rootlist, class);
2280         g_hash_table_insert (image->array_cache, eclass, list);
2281
2282         mono_loader_unlock ();
2283
2284         return class;
2285 }
2286
2287 /**
2288  * mono_array_class_get:
2289  * @element_class: element class 
2290  * @rank: the dimension of the array class
2291  *
2292  * Returns: a class object describing the array with element type @element_type and 
2293  * dimension @rank. 
2294  */
2295 MonoClass *
2296 mono_array_class_get (MonoClass *eclass, guint32 rank)
2297 {
2298         return mono_bounded_array_class_get (eclass, rank, FALSE);
2299 }
2300
2301 /**
2302  * mono_class_instance_size:
2303  * @klass: a class 
2304  * 
2305  * Returns: the size of an object instance
2306  */
2307 gint32
2308 mono_class_instance_size (MonoClass *klass)
2309 {       
2310         if (!klass->size_inited)
2311                 mono_class_init (klass);
2312
2313         return klass->instance_size;
2314 }
2315
2316 /**
2317  * mono_class_min_align:
2318  * @klass: a class 
2319  * 
2320  * Returns: minimm alignment requirements 
2321  */
2322 gint32
2323 mono_class_min_align (MonoClass *klass)
2324 {       
2325         if (!klass->size_inited)
2326                 mono_class_init (klass);
2327
2328         return klass->min_align;
2329 }
2330
2331 /**
2332  * mono_class_value_size:
2333  * @klass: a class 
2334  *
2335  * This function is used for value types, and return the
2336  * space and the alignment to store that kind of value object.
2337  *
2338  * Returns: the size of a value of kind @klass
2339  */
2340 gint32
2341 mono_class_value_size      (MonoClass *klass, guint32 *align)
2342 {
2343         gint32 size;
2344
2345         /* fixme: check disable, because we still have external revereces to
2346          * mscorlib and Dummy Objects 
2347          */
2348         /*g_assert (klass->valuetype);*/
2349
2350         size = mono_class_instance_size (klass) - sizeof (MonoObject);
2351
2352         if (align)
2353                 *align = klass->min_align;
2354
2355         return size;
2356 }
2357
2358 /**
2359  * mono_class_data_size:
2360  * @klass: a class 
2361  * 
2362  * Returns: the size of the static class data
2363  */
2364 gint32
2365 mono_class_data_size (MonoClass *klass)
2366 {       
2367         if (!klass->inited)
2368                 mono_class_init (klass);
2369
2370         return klass->class_size;
2371 }
2372
2373 /*
2374  * Auxiliary routine to mono_class_get_field
2375  *
2376  * Takes a field index instead of a field token.
2377  */
2378 static MonoClassField *
2379 mono_class_get_field_idx (MonoClass *class, int idx)
2380 {
2381         if (class->field.count){
2382                 if ((idx >= class->field.first) && (idx < class->field.last)){
2383                         return &class->fields [idx - class->field.first];
2384                 }
2385         }
2386
2387         if (!class->parent)
2388                 return NULL;
2389         
2390         return mono_class_get_field_idx (class->parent, idx);
2391 }
2392
2393 /**
2394  * mono_class_get_field:
2395  * @class: the class to lookup the field.
2396  * @field_token: the field token
2397  *
2398  * Returns: A MonoClassField representing the type and offset of
2399  * the field, or a NULL value if the field does not belong to this
2400  * class.
2401  */
2402 MonoClassField *
2403 mono_class_get_field (MonoClass *class, guint32 field_token)
2404 {
2405         int idx = mono_metadata_token_index (field_token);
2406
2407         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
2408
2409         return mono_class_get_field_idx (class, idx - 1);
2410 }
2411
2412 MonoClassField *
2413 mono_class_get_field_from_name (MonoClass *klass, const char *name)
2414 {
2415         int i;
2416
2417         while (klass) {
2418                 for (i = 0; i < klass->field.count; ++i) {
2419                         if (strcmp (name, klass->fields [i].name) == 0)
2420                                 return &klass->fields [i];
2421                 }
2422                 klass = klass->parent;
2423         }
2424         return NULL;
2425 }
2426
2427 void *
2428 mono_vtable_get_static_field_data (MonoVTable *vt)
2429 {
2430         return vt->data;
2431 }
2432
2433 MonoProperty*
2434 mono_class_get_property_from_name (MonoClass *klass, const char *name)
2435 {
2436         int i;
2437
2438         while (klass) {
2439                 for (i = 0; i < klass->property.count; ++i) {
2440                         if (strcmp (name, klass->properties [i].name) == 0)
2441                                 return &klass->properties [i];
2442                 }
2443                 klass = klass->parent;
2444         }
2445         return NULL;
2446 }
2447
2448 /**
2449  * mono_class_get:
2450  * @image: the image where the class resides
2451  * @type_token: the token for the class
2452  * @at: an optional pointer to return the array element type
2453  *
2454  * Returns: the MonoClass that represents @type_token in @image
2455  */
2456 MonoClass *
2457 mono_class_get (MonoImage *image, guint32 type_token)
2458 {
2459         MonoClass *class = NULL;
2460
2461         if (image->dynamic)
2462                 return mono_lookup_dynamic_token (image, type_token);
2463
2464         switch (type_token & 0xff000000){
2465         case MONO_TOKEN_TYPE_DEF:
2466                 class = mono_class_create_from_typedef (image, type_token);
2467                 break;          
2468         case MONO_TOKEN_TYPE_REF:
2469                 class = mono_class_from_typeref (image, type_token);
2470                 break;
2471         case MONO_TOKEN_TYPE_SPEC:
2472                 class = mono_class_create_from_typespec (image, type_token, NULL);
2473                 break;
2474         default:
2475                 g_warning ("unknown token type %x", type_token & 0xff000000);
2476                 g_assert_not_reached ();
2477         }
2478
2479         if (!class)
2480                 g_warning ("Could not load class from token 0x%08x in %s", type_token, image->name);
2481
2482         return class;
2483 }
2484
2485 MonoClass *
2486 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
2487 {
2488         MonoClass *class = mono_class_get (image, type_token);
2489         MonoType *inflated;
2490
2491         if (!class || !context)
2492                 return class;
2493
2494         switch (class->byval_arg.type) {
2495         case MONO_TYPE_GENERICINST:
2496                 if (!class->generic_inst->is_open)
2497                         return class;
2498                 break;
2499         case MONO_TYPE_VAR:
2500         case MONO_TYPE_MVAR:
2501                 break;
2502         default:
2503                 return class;
2504         }
2505
2506         inflated = inflate_generic_type (&class->byval_arg, context);
2507         if (!inflated)
2508                 return class;
2509
2510         return mono_class_from_mono_type (inflated);
2511 }
2512
2513 /**
2514  * mono_class_from_name_case:
2515  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
2516  * @name_space: the type namespace
2517  * @name: the type short name.
2518  *
2519  * Obtains a MonoClass with a given namespace and a given name which
2520  * is located in the given MonoImage.   The namespace and name
2521  * lookups are case insensitive.
2522  *
2523  * You can also pass `NULL' to the image, and that will lookup for
2524  * a type with the given namespace and name in all of the loaded
2525  * assemblies: notice that since there might be a name clash in this
2526  * case, passing NULL is not encouraged if you need a precise type.
2527  *
2528  */
2529 MonoClass *
2530 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
2531 {
2532         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
2533         guint32 cols [MONO_TYPEDEF_SIZE];
2534         const char *n;
2535         const char *nspace;
2536         guint32 i, visib;
2537
2538         /* add a cache if needed */
2539         for (i = 1; i <= t->rows; ++i) {
2540                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
2541                 /* nested types are accessed from the nesting name */
2542                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2543                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
2544                         continue;
2545                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2546                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2547                 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
2548                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
2549         }
2550         return NULL;
2551 }
2552
2553 static MonoClass*
2554 return_nested_in (MonoClass *class, char *nested) {
2555         MonoClass *found;
2556         char *s = strchr (nested, '/');
2557         GList *tmp;
2558
2559         if (s) {
2560                 *s = 0;
2561                 s++;
2562         }
2563         for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
2564                 found = tmp->data;
2565                 if (strcmp (found->name, nested) == 0) {
2566                         if (s)
2567                                 return return_nested_in (found, s);
2568                         return found;
2569                 }
2570         }
2571         return NULL;
2572 }
2573
2574
2575 /**
2576  * mono_class_from_name_case:
2577  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
2578  * @name_space: the type namespace
2579  * @name: the type short name.
2580  *
2581  * Obtains a MonoClass with a given namespace and a given name which
2582  * is located in the given MonoImage.   
2583  *
2584  * You can also pass `NULL' to the image, and that will lookup for
2585  * a type with the given namespace and name in all of the loaded
2586  * assemblies: notice that since there might be a name clash in this
2587  * case, passing NULL is not encouraged if you need a precise type.
2588  *
2589  */
2590 MonoClass *
2591 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
2592 {
2593         GHashTable *nspace_table;
2594         MonoImage *loaded_image;
2595         guint32 token = 0;
2596         MonoClass *class;
2597         char *nested;
2598         char buf [1024];
2599
2600         if ((nested = strchr (name, '/'))) {
2601                 int pos = nested - name;
2602                 int len = strlen (name);
2603                 if (len > 1023)
2604                         return NULL;
2605                 memcpy (buf, name, len + 1);
2606                 buf [pos] = 0;
2607                 nested = buf + pos + 1;
2608                 name = buf;
2609         }
2610
2611         mono_loader_lock ();
2612
2613         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
2614
2615         if (nspace_table)
2616                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
2617
2618         mono_loader_unlock ();
2619
2620         if (!token)
2621                 return NULL;
2622
2623         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
2624                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
2625                 guint32 cols [MONO_EXP_TYPE_SIZE];
2626                 guint32 idx, impl;
2627
2628                 idx = mono_metadata_token_index (token);
2629
2630                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
2631
2632                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
2633                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
2634                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
2635                         if (!loaded_image)
2636                                 return NULL;
2637                         class = mono_class_from_name (loaded_image, name_space, name);
2638                         if (nested)
2639                                 return return_nested_in (class, nested);
2640                         return class;
2641                 } else {
2642                         g_error ("not yet implemented");
2643                 }
2644         }
2645
2646         token = MONO_TOKEN_TYPE_DEF | token;
2647
2648         class = mono_class_get (image, token);
2649         if (nested)
2650                 return return_nested_in (class, nested);
2651         return class;
2652 }
2653
2654 gboolean
2655 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
2656                            gboolean check_interfaces)
2657 {
2658  again:
2659         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
2660                 if ((klassc->interface_id <= klass->max_interface_id) &&
2661                         (klass->interface_offsets [klassc->interface_id] >= 0))
2662                         return TRUE;
2663         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
2664                 int i;
2665
2666                 for (i = 0; i < klass->interface_count; i ++) {
2667                         MonoClass *ic =  klass->interfaces [i];
2668                         if (ic == klassc)
2669                                 return TRUE;
2670                 }
2671         } else {
2672                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
2673                         return TRUE;
2674                 if (klass->generic_inst) {
2675                         MonoType *parent = klass->generic_inst->parent;
2676                         if (!parent)
2677                                 return FALSE;
2678
2679                         if (mono_metadata_type_equal (parent, &klassc->byval_arg))
2680                                 return TRUE;
2681                         klass = mono_class_from_mono_type (parent);
2682                         goto again;
2683                 }
2684         }
2685
2686         /* 
2687          * MS.NET thinks interfaces are a subclass of Object, so we think it as
2688          * well.
2689          */
2690         if (klassc == mono_defaults.object_class)
2691                 return TRUE;
2692         
2693         return FALSE;
2694 }
2695
2696 gboolean
2697 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
2698 {
2699         if (!klass->inited)
2700                 mono_class_init (klass);
2701
2702         if (!oklass->inited)
2703                 mono_class_init (oklass);
2704
2705         if (MONO_CLASS_IS_INTERFACE (klass)) {
2706                 if ((klass->interface_id <= oklass->max_interface_id) &&
2707                     (oklass->interface_offsets [klass->interface_id] != -1))
2708                         return TRUE;
2709         } else
2710                 if (klass->rank) {
2711                         MonoClass *eclass, *eoclass;
2712
2713                         if (oklass->rank != klass->rank)
2714                                 return FALSE;
2715
2716                         /* vectors vs. one dimensional arrays */
2717                         if (oklass->byval_arg.type != klass->byval_arg.type)
2718                                 return FALSE;
2719
2720                         eclass = klass->cast_class;
2721                         eoclass = oklass->cast_class;
2722
2723
2724                         /* 
2725                          * a is b does not imply a[] is b[] when a is a valuetype, and
2726                          * b is a reference type.
2727                          */
2728
2729                         if (eoclass->valuetype) {
2730                                 if ((eclass == mono_defaults.enum_class) || 
2731                                         (eclass == mono_defaults.enum_class->parent) ||
2732                                         (eclass == mono_defaults.object_class))
2733                                         return FALSE;
2734                         }
2735
2736                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
2737                 }
2738         else
2739                 if (klass == mono_defaults.object_class)
2740                         return TRUE;
2741
2742         return mono_class_has_parent (oklass, klass);
2743 }       
2744
2745 /*
2746  * mono_class_needs_cctor_run:
2747  *
2748  *  Determines whenever the class has a static constructor and whenever it
2749  * needs to be called when executing CALLER.
2750  */
2751 gboolean
2752 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
2753 {
2754         int i;
2755         MonoMethod *method;
2756         
2757         for (i = 0; i < klass->method.count; ++i) {
2758                 method = klass->methods [i];
2759                 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
2760                     (strcmp (".cctor", method->name) == 0)) {
2761                         if (caller == method)
2762                                 return FALSE;
2763                         return TRUE;
2764                 }
2765         }
2766         return FALSE;
2767 }
2768
2769 /*
2770  * Returns the nnumber of bytes an element of type klass
2771  * uses when stored into an array.
2772  */
2773 gint32
2774 mono_class_array_element_size (MonoClass *klass)
2775 {
2776         int t = klass->byval_arg.type;
2777         
2778 handle_enum:
2779         switch (t) {
2780         case MONO_TYPE_I1:
2781         case MONO_TYPE_U1:
2782         case MONO_TYPE_BOOLEAN:
2783                 return 1;
2784         case MONO_TYPE_I2:
2785         case MONO_TYPE_U2:
2786         case MONO_TYPE_CHAR:
2787                 return 2;
2788         case MONO_TYPE_I4:
2789         case MONO_TYPE_U4:
2790         case MONO_TYPE_R4:
2791                 return 4;
2792         case MONO_TYPE_I:
2793         case MONO_TYPE_U:
2794         case MONO_TYPE_PTR:
2795         case MONO_TYPE_CLASS:
2796         case MONO_TYPE_STRING:
2797         case MONO_TYPE_OBJECT:
2798         case MONO_TYPE_SZARRAY:
2799         case MONO_TYPE_ARRAY: 
2800         case MONO_TYPE_VAR:
2801         case MONO_TYPE_MVAR:   
2802                 return sizeof (gpointer);
2803         case MONO_TYPE_I8:
2804         case MONO_TYPE_U8:
2805         case MONO_TYPE_R8:
2806                 return 8;
2807         case MONO_TYPE_VALUETYPE:
2808                 if (klass->enumtype) {
2809                         t = klass->enum_basetype->type;
2810                         goto handle_enum;
2811                 }
2812                 return mono_class_instance_size (klass) - sizeof (MonoObject);
2813         default:
2814                 g_error ("unknown type 0x%02x in mono_class_array_element_size", t);
2815         }
2816         return -1;
2817 }
2818
2819 /**
2820  * mono_array_element_size:
2821  * @ac: pointer to a #MonoArrayClass
2822  *
2823  * Returns: the size of single array element.
2824  */
2825 gint32
2826 mono_array_element_size (MonoClass *ac)
2827 {
2828         return mono_class_array_element_size (ac->element_class);
2829 }
2830
2831 gpointer
2832 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
2833               MonoGenericContext *context)
2834 {
2835         if (image->dynamic) {
2836                 gpointer obj = mono_lookup_dynamic_token (image, token);
2837
2838                 switch (token & 0xff000000) {
2839                 case MONO_TOKEN_TYPE_DEF:
2840                 case MONO_TOKEN_TYPE_REF:
2841                 case MONO_TOKEN_TYPE_SPEC:
2842                         if (handle_class)
2843                                 *handle_class = mono_defaults.typehandle_class;
2844                         return &((MonoClass*)obj)->byval_arg;
2845                 case MONO_TOKEN_METHOD_DEF:
2846                         if (handle_class)
2847                                 *handle_class = mono_defaults.methodhandle_class;
2848                         return obj;
2849                 case MONO_TOKEN_FIELD_DEF:
2850                         if (handle_class)
2851                                 *handle_class = mono_defaults.fieldhandle_class;
2852                         return obj;
2853                 default:
2854                         g_assert_not_reached ();
2855                 }
2856         }
2857
2858         switch (token & 0xff000000) {
2859         case MONO_TOKEN_TYPE_DEF:
2860         case MONO_TOKEN_TYPE_REF: {
2861                 MonoClass *class;
2862                 if (handle_class)
2863                         *handle_class = mono_defaults.typehandle_class;
2864                 class = mono_class_get_full (image, token, context);
2865                 mono_class_init (class);
2866                 /* We return a MonoType* as handle */
2867                 return &class->byval_arg;
2868         }
2869         case MONO_TOKEN_TYPE_SPEC: {
2870                 MonoClass *class;
2871                 if (handle_class)
2872                         *handle_class = mono_defaults.typehandle_class;
2873                 class = mono_class_create_from_typespec (image, token, context);
2874                 mono_class_init (class);
2875                 return &class->byval_arg;
2876         }
2877         case MONO_TOKEN_FIELD_DEF: {
2878                 MonoClass *class;
2879                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
2880                 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
2881                 mono_class_init (class);
2882                 if (handle_class)
2883                         *handle_class = mono_defaults.fieldhandle_class;
2884                 return mono_class_get_field (class, token);
2885         }
2886         case MONO_TOKEN_METHOD_DEF: {
2887                 MonoMethod *meth;
2888                 meth = mono_get_method_full (image, token, NULL, context);
2889                 if (handle_class)
2890                         *handle_class = mono_defaults.methodhandle_class;
2891                 return meth;
2892         }
2893         case MONO_TOKEN_MEMBER_REF: {
2894                 guint32 cols [MONO_MEMBERREF_SIZE];
2895                 const char *sig;
2896                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
2897                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
2898                 mono_metadata_decode_blob_size (sig, &sig);
2899                 if (*sig == 0x6) { /* it's a field */
2900                         MonoClass *klass;
2901                         MonoClassField *field;
2902                         field = mono_field_from_token (image, token, &klass, context);
2903                         if (handle_class)
2904                                 *handle_class = mono_defaults.fieldhandle_class;
2905                         return field;
2906                 } else {
2907                         MonoMethod *meth;
2908                         meth = mono_get_method_full (image, token, NULL, context);
2909                         if (handle_class)
2910                                 *handle_class = mono_defaults.methodhandle_class;
2911                         return meth;
2912                 }
2913         }
2914         default:
2915                 g_warning ("Unknown token 0x%08x in ldtoken", token);
2916                 break;
2917         }
2918         return NULL;
2919 }
2920
2921 /**
2922  * This function might need to call runtime functions so it can't be part
2923  * of the metadata library.
2924  */
2925 static MonoLookupDynamicToken lookup_dynamic = NULL;
2926
2927 void
2928 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
2929 {
2930         lookup_dynamic = func;
2931 }
2932
2933 gpointer
2934 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
2935 {
2936         return lookup_dynamic (image, token);
2937 }
2938
2939 MonoImage*
2940 mono_class_get_image (MonoClass *klass)
2941 {
2942         return klass->image;
2943 }
2944
2945 /**
2946  * mono_class_get_element_class:
2947  * @klass: the MonoClass to act on
2948  *
2949  * Returns the element class of an array or an enumeration.
2950  */
2951 MonoClass*
2952 mono_class_get_element_class (MonoClass *klass)
2953 {
2954         return klass->element_class;
2955 }
2956
2957 /**
2958  * mono_class_is_valuetype:
2959  * @klass: the MonoClass to act on
2960  *
2961  * Returns true if the MonoClass represents a ValueType.
2962  */
2963 gboolean
2964 mono_class_is_valuetype (MonoClass *klass)
2965 {
2966         return klass->valuetype;
2967 }
2968
2969 /**
2970  * mono_class_is_enum:
2971  * @klass: the MonoClass to act on
2972  *
2973  * Returns true if the MonoClass represents an enumeration.
2974  */
2975 gboolean
2976 mono_class_is_enum (MonoClass *klass)
2977 {
2978         return klass->enumtype;
2979 }
2980
2981 /**
2982  * mono_class_enum_basetype:
2983  * @klass: the MonoClass to act on
2984  *
2985  * Returns the underlying type representation for an enumeration.
2986  */
2987 MonoType*
2988 mono_class_enum_basetype (MonoClass *klass)
2989 {
2990         return klass->enum_basetype;
2991 }
2992
2993 /**
2994  * mono_class_get_parent
2995  * @klass: the MonoClass to act on
2996  *
2997  * Returns the parent class for this class.
2998  */
2999 MonoClass*
3000 mono_class_get_parent (MonoClass *klass)
3001 {
3002         return klass->parent;
3003 }
3004
3005 /**
3006  * mono_class_get_nesting_type;
3007  * @klass: the MonoClass to act on
3008  *
3009  * Returns the container type where this type is nested or NULL if this type is not a nested type.
3010  */
3011 MonoClass*
3012 mono_class_get_nesting_type (MonoClass *klass)
3013 {
3014         return klass->nested_in;
3015 }
3016
3017 /**
3018  * mono_class_get_rank:
3019  * @klass: the MonoClass to act on
3020  *
3021  * Returns the rank for the array (the number of dimensions).
3022  */
3023 int
3024 mono_class_get_rank (MonoClass *klass)
3025 {
3026         return klass->rank;
3027 }
3028
3029 /**
3030  * mono_class_get_flags:
3031  * @klass: the MonoClass to act on
3032  *
3033  * The type flags from the TypeDef table from the metadata.
3034  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
3035  * different values.
3036  *
3037  * Returns the flags from the TypeDef table.
3038  */
3039 guint32
3040 mono_class_get_flags (MonoClass *klass)
3041 {
3042         return klass->flags;
3043 }
3044
3045 /**
3046  * mono_class_get_name
3047  * @klass: the MonoClass to act on
3048  *
3049  * Returns the name of the class.
3050  */
3051 const char*
3052 mono_class_get_name (MonoClass *klass)
3053 {
3054         return klass->name;
3055 }
3056
3057 /**
3058  * mono_class_get_namespace:
3059  * @klass: the MonoClass to act on
3060  *
3061  * Returns the namespace of the class.
3062  */
3063 const char*
3064 mono_class_get_namespace (MonoClass *klass)
3065 {
3066         return klass->name_space;
3067 }
3068
3069 /**
3070  * mono_class_get_type:
3071  * @klass: the MonoClass to act on
3072  *
3073  * This method returns the internal Type representation for the class.
3074  *
3075  * Returns the MonoType from the class.
3076  */
3077 MonoType*
3078 mono_class_get_type (MonoClass *klass)
3079 {
3080         return &klass->byval_arg;
3081 }
3082
3083 /**
3084  * mono_class_get_byref_type:
3085  * @klass: the MonoClass to act on
3086  *
3087  * 
3088  */
3089 MonoType*
3090 mono_class_get_byref_type (MonoClass *klass)
3091 {
3092         return &klass->this_arg;
3093 }
3094
3095 /**
3096  * mono_class_num_fields:
3097  * @klass: the MonoClass to act on
3098  *
3099  * Returns the number of static and instance fields in the class.
3100  */
3101 int
3102 mono_class_num_fields (MonoClass *klass)
3103 {
3104         return klass->field.count;
3105 }
3106
3107 /**
3108  * mono_class_num_methods:
3109  * @klass: the MonoClass to act on
3110  *
3111  * Returns the number of methods in the class.
3112  */
3113 int
3114 mono_class_num_methods (MonoClass *klass)
3115 {
3116         return klass->method.count;
3117 }
3118
3119 /**
3120  * mono_class_num_properties
3121  * @klass: the MonoClass to act on
3122  *
3123  * Returns the number of properties in the class.
3124  */
3125 int
3126 mono_class_num_properties (MonoClass *klass)
3127 {
3128         return klass->property.count;
3129 }
3130
3131 /**
3132  * mono_class_num_events:
3133  * @klass: the MonoClass to act on
3134  *
3135  * Returns the number of events in the class.
3136  */
3137 int
3138 mono_class_num_events (MonoClass *klass)
3139 {
3140         return klass->event.count;
3141 }
3142
3143 /**
3144  * mono_class_get_fields:
3145  * @klass: the MonoClass to act on
3146  *
3147  * This routine is an iterator routine for retrieving the fields in a class.
3148  *
3149  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3150  * iterate over all of the elements.  When no more values are
3151  * available, the return value is NULL.
3152  *
3153  * Returns a `MonoClassField *' on each iteration, or NULL when no more fields are available.
3154  */
3155 MonoClassField*
3156 mono_class_get_fields (MonoClass* klass, gpointer *iter)
3157 {
3158         MonoClassField* field;
3159         if (!iter)
3160                 return NULL;
3161         if (!klass->inited)
3162                 mono_class_init (klass);
3163         if (!*iter) {
3164                 /* start from the first */
3165                 if (klass->field.count) {
3166                         return *iter = &klass->fields [0];
3167                 } else {
3168                         /* no fields */
3169                         return NULL;
3170                 }
3171         }
3172         field = *iter;
3173         field++;
3174         if (field < &klass->fields [klass->field.count]) {
3175                 return *iter = field;
3176         }
3177         return NULL;
3178 }
3179
3180 /**
3181  * mono_class_get_methods
3182  * @klass: the MonoClass to act on
3183  *
3184  * This routine is an iterator routine for retrieving the fields in a class.
3185  *
3186  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3187  * iterate over all of the elements.  When no more values are
3188  * available, the return value is NULL.
3189  *
3190  * Returns a MonoMethod on each iteration or NULL when no more methods are available.
3191  */
3192 MonoMethod*
3193 mono_class_get_methods (MonoClass* klass, gpointer *iter)
3194 {
3195         MonoMethod** method;
3196         if (!iter)
3197                 return NULL;
3198         if (!klass->inited)
3199                 mono_class_init (klass);
3200         if (!*iter) {
3201                 /* start from the first */
3202                 if (klass->method.count) {
3203                         *iter = &klass->methods [0];
3204                         return klass->methods [0];
3205                 } else {
3206                         /* no method */
3207                         return NULL;
3208                 }
3209         }
3210         method = *iter;
3211         method++;
3212         if (method < &klass->methods [klass->method.count]) {
3213                 *iter = method;
3214                 return *method;
3215         }
3216         return NULL;
3217 }
3218
3219 /**
3220  * mono_class_get_properties:
3221  * @klass: the MonoClass to act on
3222  *
3223  * This routine is an iterator routine for retrieving the properties in a class.
3224  *
3225  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3226  * iterate over all of the elements.  When no more values are
3227  * available, the return value is NULL.
3228  *
3229  * Returns a `MonoProperty *' on each invocation, or NULL when no more are available.
3230  */
3231 MonoProperty*
3232 mono_class_get_properties (MonoClass* klass, gpointer *iter)
3233 {
3234         MonoProperty* property;
3235         if (!iter)
3236                 return NULL;
3237         if (!klass->inited)
3238                 mono_class_init (klass);
3239         if (!*iter) {
3240                 /* start from the first */
3241                 if (klass->property.count) {
3242                         return *iter = &klass->properties [0];
3243                 } else {
3244                         /* no fields */
3245                         return NULL;
3246                 }
3247         }
3248         property = *iter;
3249         property++;
3250         if (property < &klass->properties [klass->property.count]) {
3251                 return *iter = property;
3252         }
3253         return NULL;
3254 }
3255
3256 /**
3257  * mono_class_get_events:
3258  * @klass: the MonoClass to act on
3259  *
3260  * This routine is an iterator routine for retrieving the properties in a class.
3261  *
3262  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3263  * iterate over all of the elements.  When no more values are
3264  * available, the return value is NULL.
3265  *
3266  * Returns a `MonoEvent *' on each invocation, or NULL when no more are available.
3267  */
3268 MonoEvent*
3269 mono_class_get_events (MonoClass* klass, gpointer *iter)
3270 {
3271         MonoEvent* event;
3272         if (!iter)
3273                 return NULL;
3274         if (!klass->inited)
3275                 mono_class_init (klass);
3276         if (!*iter) {
3277                 /* start from the first */
3278                 if (klass->event.count) {
3279                         return *iter = &klass->events [0];
3280                 } else {
3281                         /* no fields */
3282                         return NULL;
3283                 }
3284         }
3285         event = *iter;
3286         event++;
3287         if (event < &klass->events [klass->event.count]) {
3288                 return *iter = event;
3289         }
3290         return NULL;
3291 }
3292
3293 /**
3294  * mono_class_get_interfaaces
3295  * @klass: the MonoClass to act on
3296  *
3297  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
3298  *
3299  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3300  * iterate over all of the elements.  When no more values are
3301  * available, the return value is NULL.
3302  *
3303  * Returns a `Monoclass *' on each invocation, or NULL when no more are available.
3304  */
3305 MonoClass*
3306 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
3307 {
3308         MonoClass** iface;
3309         if (!iter)
3310                 return NULL;
3311         if (!klass->inited)
3312                 mono_class_init (klass);
3313         if (!*iter) {
3314                 /* start from the first */
3315                 if (klass->interface_count) {
3316                         *iter = &klass->interfaces [0];
3317                         return klass->interfaces [0];
3318                 } else {
3319                         /* no interface */
3320                         return NULL;
3321                 }
3322         }
3323         iface = *iter;
3324         iface++;
3325         if (iface < &klass->interfaces [klass->interface_count]) {
3326                 *iter = iface;
3327                 return *iface;
3328         }
3329         return NULL;
3330 }
3331
3332 /**
3333  * mono_class_get_interfaaces
3334  * @klass: the MonoClass to act on
3335  *
3336  * This routine is an iterator routine for retrieving the nested types of a class.
3337  *
3338  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3339  * iterate over all of the elements.  When no more values are
3340  * available, the return value is NULL.
3341  *
3342  * Returns a `Monoclass *' on each invocation, or NULL when no more are available.
3343  */
3344 MonoClass*
3345 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
3346 {
3347         GList *item;
3348         if (!iter)
3349                 return NULL;
3350         if (!klass->inited)
3351                 mono_class_init (klass);
3352         if (!*iter) {
3353                 /* start from the first */
3354                 if (klass->nested_classes) {
3355                         *iter = klass->nested_classes;
3356                         return klass->nested_classes->data;
3357                 } else {
3358                         /* no nested types */
3359                         return NULL;
3360                 }
3361         }
3362         item = *iter;
3363         item = item->next;
3364         if (item) {
3365                 *iter = item;
3366                 return item->data;
3367         }
3368         return NULL;
3369 }
3370
3371 /**
3372  * mono_field_get_name:
3373  * @field: the MonoClassField to act on
3374  *
3375  * Returns the name of the field.
3376  */
3377 const char*
3378 mono_field_get_name (MonoClassField *field)
3379 {
3380         return field->name;
3381 }
3382
3383 /**
3384  * mono_field_get_type:
3385  * @field: the MonoClassField to act on
3386  *
3387  * Returns MonoType of the field.
3388  */
3389 MonoType*
3390 mono_field_get_type (MonoClassField *field)
3391 {
3392         return field->type;
3393 }
3394
3395 /**
3396  * mono_field_get_type:
3397  * @field: the MonoClassField to act on
3398  *
3399  * Returns MonoClass where the field was defined.
3400  */
3401 MonoClass*
3402 mono_field_get_parent (MonoClassField *field)
3403 {
3404         return field->parent;
3405 }
3406
3407 /**
3408  * mono_field_get_flags;
3409  * @field: the MonoClassField to act on
3410  *
3411  * The metadata flags for a field are encoded using the
3412  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
3413  *
3414  * Returns the flags for the field.
3415  */
3416 guint32
3417 mono_field_get_flags (MonoClassField *field)
3418 {
3419         return field->type->attrs;
3420 }
3421
3422 /**
3423  * mono_property_get_name: 
3424  * @prop: the MonoProperty to act on
3425  *
3426  * Returns the name of the property
3427  */
3428 const char*
3429 mono_property_get_name (MonoProperty *prop)
3430 {
3431         return prop->name;
3432 }
3433
3434 /**
3435  * mono_property_get_set_method
3436  * @prop: the MonoProperty to act on.
3437  *
3438  * Returns the setter method of the property (A MonoMethod)
3439  */
3440 MonoMethod*
3441 mono_property_get_set_method (MonoProperty *prop)
3442 {
3443         return prop->set;
3444 }
3445
3446 /**
3447  * mono_property_get_get_method
3448  * @prop: the MonoProperty to act on.
3449  *
3450  * Returns the setter method of the property (A MonoMethod)
3451  */
3452 MonoMethod*
3453 mono_property_get_get_method (MonoProperty *prop)
3454 {
3455         return prop->get;
3456 }
3457
3458 /**
3459  * mono_property_get_parent:
3460  * @prop: the MonoProperty to act on.
3461  *
3462  * Returns the MonoClass where the property was defined.
3463  */
3464 MonoClass*
3465 mono_property_get_parent (MonoProperty *prop)
3466 {
3467         return prop->parent;
3468 }
3469
3470 /**
3471  * mono_property_get_flags:
3472  * @prop: the MonoProperty to act on.
3473  *
3474  * The metadata flags for a property are encoded using the
3475  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
3476  *
3477  * Returns the flags for the property.
3478  */
3479 guint32
3480 mono_property_get_flags (MonoProperty *prop)
3481 {
3482         return prop->attrs;
3483 }
3484
3485 /**
3486  * mono_event_get_name:
3487  * @event: the MonoEvent to act on
3488  *
3489  * Returns the name of the event.
3490  */
3491 const char*
3492 mono_event_get_name (MonoEvent *event)
3493 {
3494         return event->name;
3495 }
3496
3497 /**
3498  * mono_event_get_add_method:
3499  * @event: The MonoEvent to act on.
3500  *
3501  * Returns the `add' method for the event (a MonoMethod).
3502  */
3503 MonoMethod*
3504 mono_event_get_add_method (MonoEvent *event)
3505 {
3506         return event->add;
3507 }
3508
3509 /**
3510  * mono_event_get_remove_method:
3511  * @event: The MonoEvent to act on.
3512  *
3513  * Returns the `remove' method for the event (a MonoMethod).
3514  */
3515 MonoMethod*
3516 mono_event_get_remove_method (MonoEvent *event)
3517 {
3518         return event->remove;
3519 }
3520
3521 /**
3522  * mono_event_get_raise_method:
3523  * @event: The MonoEvent to act on.
3524  *
3525  * Returns the `raise' method for the event (a MonoMethod).
3526  */
3527 MonoMethod*
3528 mono_event_get_raise_method (MonoEvent *event)
3529 {
3530         return event->raise;
3531 }
3532
3533 /**
3534  * mono_event_get_parent:
3535  * @event: the MonoEvent to act on.
3536  *
3537  * Returns the MonoClass where the event is defined.
3538  */
3539 MonoClass*
3540 mono_event_get_parent (MonoEvent *event)
3541 {
3542         return event->parent;
3543 }
3544
3545 /**
3546  * mono_event_get_flags
3547  * @event: the MonoEvent to act on.
3548  *
3549  * The metadata flags for an event are encoded using the
3550  * EVENT_* constants.  See the tabledefs.h file for details.
3551  *
3552  * Returns the flags for the event.
3553  */
3554 guint32
3555 mono_event_get_flags (MonoEvent *event)
3556 {
3557         return event->attrs;
3558 }
3559