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