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