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