2002-08-14 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / metadata / class.c
1 /*
2  * class.c: Class management for the Mono runtime
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  *
9  * Possible Optimizations:
10  *     in mono_class_create, do not allocate the class right away,
11  *     but wait until you know the size of the FieldMap, so that
12  *     the class embeds directly the FieldMap after the vtable.
13  *
14  * 
15  */
16 #include <config.h>
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
31 #include <mono/metadata/debug-helpers.h>
32 #if HAVE_BOEHM_GC
33 #include <gc/gc.h>
34 #endif
35
36 #define CSIZE(x) (sizeof (x) / 4)
37
38 MonoStats mono_stats;
39
40 gboolean mono_print_vtable = FALSE;
41
42 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
43
44 MonoClass *
45 mono_class_from_typeref (MonoImage *image, guint32 type_token)
46 {
47         guint32 cols [MONO_TYPEREF_SIZE];
48         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
49         guint32 idx;
50         const char *name, *nspace;
51         MonoClass *res;
52
53         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
54
55         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
56         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
57         
58         idx = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
59         switch (cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK) {
60         case RESOLTION_SCOPE_MODULE:
61                 if (!idx)
62                         g_error ("null ResolutionScope not yet handled");
63                 /* a typedef in disguise */
64                 return mono_class_from_name (image, nspace, name);
65         case RESOLTION_SCOPE_MODULEREF:
66                 return mono_class_from_name (image->assembly->modules [idx - 1], nspace, name);
67         case RESOLTION_SCOPE_TYPEREF: {
68                 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
69                 GList *tmp;
70                 mono_class_init (enclosing);
71                 for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
72                         res = tmp->data;
73                         if (strcmp (res->name, name) == 0)
74                                 return res;
75                 }
76                 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
77                 return NULL;
78         }
79         case RESOLTION_SCOPE_ASSEMBLYREF:
80                 break;
81         }
82
83         if (!image->references ||  !image->references [idx-1]) {
84                 /* 
85                  * detected a reference to mscorlib, we simply return a reference to a dummy 
86                  * until we have a better solution.
87                  */
88                 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])); 
89                 
90                 res = mono_class_from_name (image, "System", "MonoDummy");
91                 /* prevent method loading */
92                 res->dummy = 1;
93                 /* some storage if the type is used  - very ugly hack */
94                 res->instance_size = 2*sizeof (gpointer);
95                 return res;
96         }       
97
98         /* load referenced assembly */
99         image = image->references [idx-1]->image;
100
101         return mono_class_from_name (image, nspace, name);
102 }
103
104 MonoMarshalType *
105 mono_marshal_load_type_info (MonoClass* klass)
106 {
107         int i, j, count = 0;
108         MonoMarshalType *info;
109         guint32 layout;
110
111         g_assert (klass != NULL);
112
113         if (klass->marshal_info)
114                 return klass->marshal_info;
115
116         if (!klass->inited)
117                 mono_class_init (klass);
118         
119         for (i = 0; i < klass->field.count; ++i) {
120                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
121                         continue;
122                 count++;
123         }
124
125         layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
126
127         klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
128         info->num_fields = count;
129         
130         if (klass->parent)
131                 info->native_size = mono_class_native_size (klass->parent, NULL);
132
133         for (j = i = 0; i < klass->field.count; ++i) {
134                 int size, align;
135                 
136                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
137                         continue;
138
139                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
140                         mono_metadata_field_info (klass->image, klass->field.first + i, 
141                                                   NULL, NULL, &info->fields [j].mspec);
142
143                 info->fields [j].field = &klass->fields [i];
144
145                 switch (layout) {
146                 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
147                 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
148                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
149                                                        &align, TRUE, klass->unicode);
150                         align = klass->packing_size ? MIN (klass->packing_size, align): align;  
151                         info->fields [j].offset = info->native_size;
152                         info->fields [j].offset += align - 1;
153                         info->fields [j].offset &= ~(align - 1);
154                         info->native_size = info->fields [j].offset + size;
155                         break;
156                 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
157                         /* FIXME: */
158                         info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
159                         info->native_size = klass->instance_size - sizeof (MonoObject);
160                         break;
161                 }       
162                 j++;
163         }
164
165         if (info->native_size & (klass->min_align - 1)) {
166                 info->native_size += klass->min_align - 1;
167                 info->native_size &= ~(klass->min_align - 1);
168         }
169
170         return klass->marshal_info;
171 }
172
173 /** 
174  * class_compute_field_layout:
175  * @m: pointer to the metadata.
176  * @class: The class to initialize
177  *
178  * Initializes the class->fields.
179  *
180  * Currently we only support AUTO_LAYOUT, and do not even try to do
181  * a good job at it.  This is temporary to get the code for Paolo.
182  */
183 static void
184 class_compute_field_layout (MonoClass *class)
185 {
186         MonoImage *m = class->image; 
187         const int top = class->field.count;
188         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
189         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
190         int i, blittable = TRUE;
191         guint32 rva;
192         guint32 packing_size = 0;
193
194         if (class->size_inited)
195                 return;
196
197         if (class->parent) {
198                 if (!class->parent->size_inited)
199                         class_compute_field_layout (class->parent);
200                 class->instance_size += class->parent->instance_size;
201                 class->class_size += class->parent->class_size;
202                 class->min_align = class->parent->min_align;
203         } else {
204                 class->instance_size = sizeof (MonoObject);
205                 class->min_align = 1;
206         }
207
208         if (mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &class->instance_size)) {
209                 class->instance_size += sizeof (MonoObject);
210         }
211
212         g_assert ((packing_size & 0xfffffff0) == 0);
213         class->packing_size = packing_size;
214
215         if (!top) {
216                 class->size_inited = 1;
217                 return;
218         }
219
220         class->fields = g_new0 (MonoClassField, top);
221
222         /*
223          * Fetch all the field information.
224          */
225         for (i = 0; i < top; i++){
226                 const char *sig;
227                 guint32 cols [MONO_FIELD_SIZE];
228                 int idx = class->field.first + i;
229                 
230                 mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
231                 /* The name is needed for fieldrefs */
232                 class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
233                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
234                 mono_metadata_decode_value (sig, &sig);
235                 /* FIELD signature == 0x06 */
236                 g_assert (*sig == 0x06);
237                 class->fields [i].type = mono_metadata_parse_field_type (
238                         m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
239
240                 if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) {
241                         if (class->fields [i].type->byref) {
242                                 blittable = FALSE;
243                         } else {
244                                 MonoClass *field_class = mono_class_from_mono_type (class->fields [i].type);
245                                 if (!field_class->blittable)
246                                         blittable = FALSE;
247                         }
248                 }
249
250                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
251                         mono_metadata_field_info (m, idx, NULL, &rva, NULL);
252                         if (!rva)
253                                 g_warning ("field %s in %s should have RVA data, but hasn't", class->fields [i].name, class->name);
254                         class->fields [i].data = mono_cli_rva_map (class->image->image_info, rva);
255                 }
256
257                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
258                         class->enum_basetype = class->fields [i].type;
259                         class->element_class = mono_class_from_mono_type (class->enum_basetype);
260                         blittable = class->element_class->blittable;
261                 }
262         }
263
264         if (class == mono_defaults.string_class)
265                 blittable = FALSE;
266
267         class->blittable = blittable;
268
269         if (class->enumtype && !class->enum_basetype) {
270                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
271                         G_BREAKPOINT ();
272         }
273         /*
274          * Compute field layout and total size (not considering static fields)
275          */
276         switch (layout) {
277         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
278         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
279                 for (i = 0; i < top; i++){
280                         int size, align;
281                         
282                         if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
283                                 continue;
284
285                         size = mono_type_size (class->fields [i].type, &align);
286                         
287                         /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
288                         align = class->packing_size ? MIN (class->packing_size, align): align;
289                         class->min_align = MAX (align, class->min_align);
290                         class->fields [i].offset = class->instance_size;
291                         class->fields [i].offset += align - 1;
292                         class->fields [i].offset &= ~(align - 1);
293                         class->instance_size = class->fields [i].offset + size;
294
295                 }
296        
297                 if (class->instance_size & (class->min_align - 1)) {
298                         class->instance_size += class->min_align - 1;
299                         class->instance_size &= ~(class->min_align - 1);
300                 }
301                 break;
302         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
303                 for (i = 0; i < top; i++) {
304                         int size, align;
305                         int idx = class->field.first + i;
306
307                         /*
308                          * There must be info about all the fields in a type if it
309                          * uses explicit layout.
310                          */
311
312                         if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
313                                 continue;
314
315                         size = mono_type_size (class->fields [i].type, &align);
316                         
317                         mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
318                         if (class->fields [i].offset == (guint32)-1)
319                                 g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
320                         /*
321                          * The offset is from the start of the object: this works for both
322                          * classes and valuetypes.
323                          */
324                         class->fields [i].offset += sizeof (MonoObject);
325                         /*
326                          * Calc max size.
327                          */
328                         class->instance_size = MAX (class->instance_size, size + class->fields [i].offset);
329                 }
330                 break;
331         }
332
333         class->size_inited = 1;
334
335         /*
336          * Compute static field layout and size
337          */
338         switch (layout) {
339         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
340         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
341                 for (i = 0; i < top; i++){
342                         int size, align;
343                         
344                         if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
345                                 continue;
346                         
347                         size = mono_type_size (class->fields [i].type, &align);
348                         class->fields [i].offset = class->class_size;
349                         class->fields [i].offset += align - 1;
350                         class->fields [i].offset &= ~(align - 1);
351                         class->class_size = class->fields [i].offset + size;
352                 }
353                 break;
354         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
355                 for (i = 0; i < top; i++){
356                         int size, align;
357
358                         /*
359                          * There must be info about all the fields in a type if it
360                          * uses explicit layout.
361                          */
362
363                         
364                         if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
365                                 continue;
366
367                         size = mono_type_size (class->fields [i].type, &align);
368                         class->fields [i].offset = class->class_size;
369                         class->fields [i].offset += align - 1;
370                         class->fields [i].offset &= ~(align - 1);
371                         class->class_size = class->fields [i].offset + size;
372                 }
373                 break;
374         }
375 }
376
377 static void
378 init_properties (MonoClass *class)
379 {
380         guint startm, endm, i, j;
381         guint32 cols [MONO_PROPERTY_SIZE];
382         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
383         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
384
385         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
386         class->property.count = class->property.last - class->property.first;
387
388         class->properties = g_new0 (MonoProperty, class->property.count);
389         for (i = class->property.first; i < class->property.last; ++i) {
390                 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
391                 class->properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
392                 class->properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
393
394                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
395                 for (j = startm; j < endm; ++j) {
396                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
397                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
398                         case METHOD_SEMANTIC_SETTER:
399                                 class->properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
400                                 break;
401                         case METHOD_SEMANTIC_GETTER:
402                                 class->properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
403                                 break;
404                         default:
405                                 break;
406                         }
407                 }
408         }
409 }
410
411 static void
412 init_events (MonoClass *class)
413 {
414         guint startm, endm, i, j;
415         guint32 cols [MONO_EVENT_SIZE];
416         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
417         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
418
419         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
420         class->event.count = class->event.last - class->event.first;
421
422         class->events = g_new0 (MonoEvent, class->event.count);
423         for (i = class->event.first; i < class->event.last; ++i) {
424                 mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
425                 class->events [i - class->event.first].attrs = cols [MONO_EVENT_FLAGS];
426                 class->events [i - class->event.first].name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
427
428                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
429                 for (j = startm; j < endm; ++j) {
430                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
431                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
432                         case METHOD_SEMANTIC_ADD_ON:
433                                 class->events [i - class->event.first].add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
434                                 break;
435                         case METHOD_SEMANTIC_REMOVE_ON:
436                                 class->events [i - class->event.first].remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
437                                 break;
438                         case METHOD_SEMANTIC_FIRE:
439                                 class->events [i - class->event.first].raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
440                                 break;
441                         case METHOD_SEMANTIC_OTHER: /* don't care for now */
442                         default:
443                                 break;
444                         }
445                 }
446         }
447 }
448
449 static guint
450 mono_get_unique_iid (MonoClass *class)
451 {
452         static GHashTable *iid_hash = NULL;
453         static guint iid = 0;
454
455         char *str;
456         gpointer value;
457         
458         g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE);
459
460         if (!iid_hash)
461                 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
462
463         str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
464
465         if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
466                 g_free (str);
467                 return (guint)value;
468         } else {
469                 g_hash_table_insert (iid_hash, str, (gpointer)iid);
470                 ++iid;
471         }
472
473         return iid - 1;
474 }
475
476 void
477 mono_class_setup_vtable (MonoClass *class)
478 {
479         MonoClass *k, *ic;
480         MonoMethod **vtable;
481         int i, onum = 0, max_vtsize = 0, max_iid, cur_slot = 0;
482         MonoMethod **overrides;
483
484         for (i = 0; i < class->interface_count; i++) 
485                 max_vtsize += class->interfaces [i]->method.count;
486         
487         if (class->parent) {
488                 max_vtsize += class->parent->vtable_size;
489                 cur_slot = class->parent->vtable_size;
490         }
491
492         max_vtsize += class->method.count;
493
494         vtable = alloca (sizeof (gpointer) * max_vtsize);
495         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
496
497         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
498
499         /* compute maximum number of slots and maximum interface id */
500         max_iid = 0;
501         for (k = class; k ; k = k->parent) {
502                 for (i = 0; i < k->interface_count; i++) {
503                         ic = k->interfaces [i];
504
505                         if (!ic->inited)
506                                 mono_class_init (ic);
507
508                         if (max_iid < ic->interface_id)
509                                 max_iid = ic->interface_id;
510                 }
511         }
512         
513         class->max_interface_id = max_iid;
514         /* compute vtable offset for interfaces */
515         class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
516
517         for (i = 0; i <= max_iid; i++)
518                 class->interface_offsets [i] = -1;
519
520         for (i = 0; i < class->interface_count; i++) {
521                 ic = class->interfaces [i];
522                 class->interface_offsets [ic->interface_id] = cur_slot;
523                 cur_slot += ic->method.count;
524         }
525
526         for (k = class->parent; k ; k = k->parent) {
527                 for (i = 0; i < k->interface_count; i++) {
528                         ic = k->interfaces [i]; 
529                         if (class->interface_offsets [ic->interface_id] == -1) {
530                                 int io = k->interface_offsets [ic->interface_id];
531
532                                 g_assert (io >= 0);
533                                 g_assert (io <= max_vtsize);
534
535                                 class->interface_offsets [ic->interface_id] = io;
536                         }
537                 }
538         }
539
540         if (class->parent && class->parent->vtable_size)
541                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
542
543         overrides = mono_class_get_overrides (class->image, class->type_token, &onum);
544
545         /* override interface methods */
546         for (i = 0; i < onum; i++) {
547                 MonoMethod *decl = overrides [i*2];
548                 if (decl->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
549                         int dslot;
550                         g_assert (decl->slot != -1);
551                         dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
552                         vtable [dslot] = overrides [i*2 + 1];
553                 }
554         }
555
556         for (k = class; k ; k = k->parent) {
557                 for (i = 0; i < k->interface_count; i++) {
558                         int j, l, io;
559
560                         ic = k->interfaces [i];
561                         io = k->interface_offsets [ic->interface_id];
562                         
563                         g_assert (io >= 0);
564                         g_assert (io <= max_vtsize);
565
566                         if (k == class) {
567                                 for (l = 0; l < ic->method.count; l++) {
568                                         MonoMethod *im = ic->methods [l];                                               
569                                         for (j = 0; j < class->method.count; ++j) {
570                                                 MonoMethod *cm = class->methods [j];
571                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
572                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC) ||
573                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
574                                                         continue;
575                                                 if (!strcmp(cm->name, im->name) && 
576                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
577                                                         g_assert (io + l <= max_vtsize);
578                                                         vtable [io + l] = cm;
579                                                 }
580                                         }
581                                 }
582                         } else {
583                                 /* already implemented */
584                                 if (io >= k->vtable_size)
585                                         continue;
586                         }
587                                 
588                         for (l = 0; l < ic->method.count; l++) {
589                                 MonoMethod *im = ic->methods [l];                                               
590                                 MonoClass *k1;
591
592                                 g_assert (io + l <= max_vtsize);
593
594                                 if (vtable [io + l])
595                                         continue;
596                                         
597                                 for (k1 = class; k1; k1 = k1->parent) {
598                                         for (j = 0; j < k1->method.count; ++j) {
599                                                 MonoMethod *cm = k1->methods [j];
600
601                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
602                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
603                                                         continue;
604                                                 
605                                                 if (!strcmp(cm->name, im->name) && 
606                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
607                                                         g_assert (io + l <= max_vtsize);
608                                                         vtable [io + l] = cm;
609                                                         break;
610                                                 }
611                                                 
612                                         }
613                                         g_assert (io + l <= max_vtsize);
614                                         if (vtable [io + l])
615                                                 break;
616                                 }
617                         }
618
619                         for (l = 0; l < ic->method.count; l++) {
620                                 MonoMethod *im = ic->methods [l];                                               
621                                 char *qname, *fqname;
622                                 
623                                 qname = g_strconcat (ic->name, ".", im->name, NULL); 
624                                 if (ic->name_space && ic->name_space [0])
625                                         fqname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
626                                 else
627                                         fqname = NULL;
628
629                                 for (j = 0; j < class->method.count; ++j) {
630                                         MonoMethod *cm = class->methods [j];
631
632                                         if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
633                                                 continue;
634                                         
635                                         if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
636                                             mono_metadata_signature_equal (cm->signature, im->signature)) {
637                                                 g_assert (io + l <= max_vtsize);
638                                                 vtable [io + l] = cm;
639                                                 break;
640                                         }
641                                 }
642                                 g_free (qname);
643                                 g_free (fqname);
644                         }
645
646                         
647                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
648                                 for (l = 0; l < ic->method.count; l++) {
649                                         char *msig;
650                                         MonoMethod *im = ic->methods [l];                                               
651                                         g_assert (io + l <= max_vtsize);
652                                         if (!(vtable [io + l])) {
653                                                 for (j = 0; j < onum; ++j) {
654                                                         g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
655                                                                  overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
656                                                 }
657                                                 msig = mono_signature_get_desc (im->signature, FALSE);
658                                                 printf ("no implementation for interface method %s.%s::%s(%s) in class %s.%s\n",
659                                                         ic->name_space, ic->name, im->name, msig, class->name_space, class->name);
660                                                 g_free (msig);
661                                                 for (j = 0; j < class->method.count; ++j) {
662                                                         MonoMethod *cm = class->methods [j];
663                                                         msig = mono_signature_get_desc (cm->signature, FALSE);
664                                                         
665                                                         printf ("METHOD %s(%s)\n", cm->name, msig);
666                                                         g_free (msig);
667                                                 }
668                                                 g_assert_not_reached ();
669                                         }
670                                 }
671                         }
672                 
673                         for (l = 0; l < ic->method.count; l++) {
674                                 MonoMethod *im = vtable [io + l];
675
676                                 if (im) {
677                                         g_assert (io + l <= max_vtsize);
678                                         if (im->slot < 0) {
679                                                 /* FIXME: why do we need this ? */
680                                                 im->slot = io + l;
681                                                 /* g_assert_not_reached (); */
682                                         }
683                                 }
684                         }
685                 }
686         } 
687
688         for (i = 0; i < class->method.count; ++i) {
689                 MonoMethod *cm;
690                
691                 cm = class->methods [i];
692
693                 
694 #if 0
695                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
696                     (cm->slot >= 0))
697                         continue;
698 #else  /* EXT_VTABLE_HACK */
699                 if (cm->slot >= 0)
700                         continue;
701 #endif
702
703                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && (cm->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
704                         for (k = class->parent; k ; k = k->parent) {
705                                 int j;
706                                 for (j = 0; j < k->method.count; ++j) {
707                                         MonoMethod *m1 = k->methods [j];
708                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
709                                                 continue;
710                                         if (!strcmp(cm->name, m1->name) && 
711                                             mono_metadata_signature_equal (cm->signature, m1->signature)) {
712                                                 cm->slot = k->methods [j]->slot;
713                                                 g_assert (cm->slot < max_vtsize);
714                                                 break;
715                                         }
716                                 }
717                                 if (cm->slot >= 0) 
718                                         break;
719                         }
720                 }
721
722                 if (cm->slot < 0)
723                         cm->slot = cur_slot++;
724
725                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
726                         vtable [cm->slot] = cm;
727         }
728
729         /* override non interface methods */
730         for (i = 0; i < onum; i++) {
731                 MonoMethod *decl = overrides [i*2];
732                 if (!(decl->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
733                         g_assert (decl->slot != -1);
734                         vtable [decl->slot] = overrides [i*2 + 1];
735                 }
736         }
737        
738         g_free (overrides);
739
740         class->vtable_size = cur_slot;
741         class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
742         memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
743
744         if (mono_print_vtable) {
745                 int icount = 0;
746
747                 for (i = 0; i <= max_iid; i++)
748                         if (class->interface_offsets [i] != -1)
749                                 icount++;
750
751                 printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space, 
752                         class->name, class->vtable_size, icount); 
753
754                 for (i = 0; i < class->vtable_size; ++i) {
755                         MonoMethod *cm;
756                
757                         cm = vtable [i];
758                         if (cm) {
759                                 printf ("  slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
760                                         cm->klass->name_space, cm->klass->name,
761                                         cm->name);
762                         }
763                 }
764
765
766                 if (icount) {
767                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
768                                 class->name, max_iid);
769         
770                         for (i = 0; i < class->interface_count; i++) {
771                                 ic = class->interfaces [i];
772                                 printf ("  slot %03d(%03d) %s.%s\n",  
773                                         class->interface_offsets [ic->interface_id],
774                                         ic->method.count, ic->name_space, ic->name);
775                         }
776
777                         for (k = class->parent; k ; k = k->parent) {
778                                 for (i = 0; i < k->interface_count; i++) {
779                                         ic = k->interfaces [i]; 
780                                         printf ("  slot %03d(%03d) %s.%s\n", 
781                                                 class->interface_offsets [ic->interface_id],
782                                                 ic->method.count, ic->name_space, ic->name);
783                                 }
784                         }
785                 }
786         }
787
788 }
789
790 /**
791  * mono_class_init:
792  * @class: the class to initialize
793  *
794  * compute the instance_size, class_size and other infos that cannot be 
795  * computed at mono_class_get() time. Also compute a generic vtable and 
796  * the method slot numbers. We use this infos later to create a domain
797  * specific vtable.  
798  */
799 void
800 mono_class_init (MonoClass *class)
801 {
802         int i;
803         static MonoMethod *default_ghc = NULL;
804         static MonoMethod *default_finalize = NULL;
805         static int finalize_slot = -1;
806         static int ghc_slot = -1;
807
808         g_assert (class);
809
810         if (class->inited)
811                 return;
812
813         if (class->init_pending) {
814                 /* this indicates a cyclic dependency */
815                 g_error ("pending init %s.%s\n", class->name_space, class->name);
816         }
817
818         class->init_pending = 1;
819
820         mono_stats.initialized_class_count++;
821
822         if (class->parent && !class->parent->inited)
823                 mono_class_init (class->parent);
824
825         /*
826          * Computes the size used by the fields, and their locations
827          */
828         if (!class->size_inited)
829                 class_compute_field_layout (class);
830
831         /* initialize method pointers */
832         class->methods = g_new (MonoMethod*, class->method.count);
833         for (i = 0; i < class->method.count; ++i)
834                 class->methods [i] = mono_get_method (class->image,
835                         MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
836
837         init_properties (class);
838         init_events (class);
839
840         i = mono_metadata_nesting_typedef (class->image, class->type_token);
841         while (i) {
842                 MonoClass* nclass;
843                 guint32 cols [MONO_NESTED_CLASS_SIZE];
844                 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
845                 if (cols [MONO_NESTED_CLASS_ENCLOSING] != mono_metadata_token_index (class->type_token))
846                         break;
847                 nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
848                 class->nested_classes = g_list_prepend (class->nested_classes, nclass);
849                 ++i;
850         }
851
852         if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
853                 for (i = 0; i < class->method.count; ++i)
854                         class->methods [i]->slot = i;
855                 class->init_pending = 0;
856                 class->inited = 1;
857                 return;
858         }
859
860         mono_class_setup_vtable (class);
861
862         class->inited = 1;
863         class->init_pending = 0;
864
865         if (!default_ghc) {
866                 if (class == mono_defaults.object_class) { 
867                        
868                         for (i = 0; i < class->vtable_size; ++i) {
869                                 MonoMethod *cm = class->vtable [i];
870                
871                                 if (!strcmp (cm->name, "GetHashCode")) {
872                                         ghc_slot = i;
873                                         break;
874                                 }
875                         }
876
877                         g_assert (ghc_slot > 0);
878
879                         default_ghc = class->vtable [ghc_slot];
880                 }
881         }
882         
883         class->ghcimpl = 1;
884         if (class != mono_defaults.object_class) { 
885
886                 if (class->vtable [ghc_slot] == default_ghc) {
887                         class->ghcimpl = 0;
888                 }
889         }
890
891         if (!default_finalize) {
892                 if (class == mono_defaults.object_class) { 
893                        
894                         for (i = 0; i < class->vtable_size; ++i) {
895                                 MonoMethod *cm = class->vtable [i];
896                
897                                 if (!strcmp (cm->name, "Finalize")) {
898                                         finalize_slot = i;
899                                         break;
900                                 }
901                         }
902
903                         g_assert (finalize_slot > 0);
904
905                         default_finalize = class->vtable [finalize_slot];
906                 }
907         }
908
909         /* Object::Finalize should have empty implemenatation */
910         class->has_finalize = 0;
911         if (class != mono_defaults.object_class) { 
912                 if (class->vtable [finalize_slot] != default_finalize)
913                         class->has_finalize = 1;
914         }
915 }
916
917
918 /*
919  * Compute a relative numbering of the class hierarchy as described in
920  * "Java for Large-Scale Scientific Computations?"
921  */
922 static void
923 mono_compute_relative_numbering (MonoClass *class, int *c)
924 {
925         GList *s;
926
927         (*c)++;
928
929         class->baseval = *c;
930
931         for (s = class->subclasses; s; s = s->next)
932                 mono_compute_relative_numbering ((MonoClass *)s->data, c); 
933         
934         class->diffval = *c -  class->baseval;
935 }
936
937 void
938 mono_class_setup_mono_type (MonoClass *class)
939 {
940         const char *name = class->name;
941         const char *nspace = class->name_space;
942
943         class->this_arg.byref = 1;
944         class->this_arg.data.klass = class;
945         class->this_arg.type = MONO_TYPE_CLASS;
946         class->byval_arg.data.klass = class;
947         class->byval_arg.type = MONO_TYPE_CLASS;
948
949         if (!strcmp (nspace, "System")) {
950                 if (!strcmp (name, "ValueType")) {
951                         /*
952                          * do not set the valuetype bit for System.ValueType.
953                          * class->valuetype = 1;
954                          */
955                 } else if (!strcmp (name, "Enum")) {
956                         /*
957                          * do not set the valuetype bit for System.Enum.
958                          * class->valuetype = 1;
959                          */
960                         class->valuetype = 0;
961                         class->enumtype = 0;
962                 } else if (!strcmp (name, "Object")) {
963                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
964                 } else if (!strcmp (name, "String")) {
965                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
966                 }
967         }
968         
969         if (class->valuetype) {
970                 int t = MONO_TYPE_VALUETYPE;
971                 if (!strcmp (nspace, "System")) {
972                         switch (*name) {
973                         case 'B':
974                                 if (!strcmp (name, "Boolean")) {
975                                         t = MONO_TYPE_BOOLEAN;
976                                 } else if (!strcmp(name, "Byte")) {
977                                         t = MONO_TYPE_U1;
978                                         class->blittable = TRUE;                                                
979                                 }
980                                 break;
981                         case 'C':
982                                 if (!strcmp (name, "Char")) {
983                                         t = MONO_TYPE_CHAR;
984                                 }
985                                 break;
986                         case 'D':
987                                 if (!strcmp (name, "Double")) {
988                                         t = MONO_TYPE_R8;
989                                         class->blittable = TRUE;                                                
990                                 }
991                                 break;
992                         case 'I':
993                                 if (!strcmp (name, "Int32")) {
994                                         t = MONO_TYPE_I4;
995                                         class->blittable = TRUE;
996                                 } else if (!strcmp(name, "Int16")) {
997                                         t = MONO_TYPE_I2;
998                                         class->blittable = TRUE;
999                                 } else if (!strcmp(name, "Int64")) {
1000                                         t = MONO_TYPE_I8;
1001                                         class->blittable = TRUE;
1002                                 } else if (!strcmp(name, "IntPtr")) {
1003                                         t = MONO_TYPE_I;
1004                                         class->blittable = TRUE;
1005                                 }
1006                                 break;
1007                         case 'S':
1008                                 if (!strcmp (name, "Single")) {
1009                                         t = MONO_TYPE_R4;
1010                                         class->blittable = TRUE;                                                
1011                                 } else if (!strcmp(name, "SByte")) {
1012                                         t = MONO_TYPE_I1;
1013                                         class->blittable = TRUE;
1014                                 }
1015                                 break;
1016                         case 'U':
1017                                 if (!strcmp (name, "UInt32")) {
1018                                         t = MONO_TYPE_U4;
1019                                         class->blittable = TRUE;
1020                                 } else if (!strcmp(name, "UInt16")) {
1021                                         t = MONO_TYPE_U2;
1022                                         class->blittable = TRUE;
1023                                 } else if (!strcmp(name, "UInt64")) {
1024                                         t = MONO_TYPE_U8;
1025                                         class->blittable = TRUE;
1026                                 } else if (!strcmp(name, "UIntPtr")) {
1027                                         t = MONO_TYPE_U;
1028                                         class->blittable = TRUE;
1029                                 }
1030                                 break;
1031                         case 'V':
1032                                 if (!strcmp (name, "Void")) {
1033                                         t = MONO_TYPE_VOID;
1034                                 }
1035                                 break;
1036                         default:
1037                                 break;
1038                         }
1039                 }
1040                 class->this_arg.type = class->byval_arg.type = t;
1041         }
1042 }
1043
1044 void
1045 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
1046 {
1047         gboolean system_namespace;
1048
1049         system_namespace = !strcmp (class->name_space, "System");
1050
1051         /* if root of the hierarchy */
1052         if (system_namespace && !strcmp (class->name, "Object")) {
1053                 class->parent = NULL;
1054                 class->instance_size = sizeof (MonoObject);
1055                 return;
1056         }
1057         if (!strcmp (class->name, "<Module>")) {
1058                 class->parent = NULL;
1059                 class->instance_size = 0;
1060                 return;
1061         }
1062
1063         if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1064                 int rnum = 0;
1065                 class->parent = parent;
1066
1067                 if (!parent)
1068                         g_assert_not_reached (); /* FIXME */
1069
1070                 class->marshalbyref = parent->marshalbyref;
1071                 class->contextbound  = parent->contextbound;
1072                 class->delegate  = parent->delegate;
1073                 
1074                 if (system_namespace) {
1075                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
1076                                 class->marshalbyref = 1;
1077
1078                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
1079                                 class->contextbound  = 1;
1080
1081                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
1082                                 class->delegate  = 1;
1083                 }
1084
1085                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
1086                                                 (strcmp (class->parent->name_space, "System") == 0)))
1087                         class->valuetype = 1;
1088                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
1089                         class->valuetype = class->enumtype = 1;
1090                 }
1091                 /*class->enumtype = class->parent->enumtype; */
1092                 class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
1093                 mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
1094         } else {
1095                 class->parent = NULL;
1096         }
1097
1098 }
1099
1100 /**
1101  * @image: context where the image is created
1102  * @type_token:  typedef token
1103  */
1104 static MonoClass *
1105 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
1106 {
1107         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
1108         MonoClass *class, *parent = NULL;
1109         guint32 cols [MONO_TYPEDEF_SIZE];
1110         guint32 cols_next [MONO_TYPEDEF_SIZE];
1111         guint tidx = mono_metadata_token_index (type_token);
1112         const char *name, *nspace;
1113         guint icount = 0; 
1114         MonoClass **interfaces;
1115
1116         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) 
1117                 return class;
1118
1119         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
1120         
1121         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
1122         
1123         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1124         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1125
1126         if (cols [MONO_TYPEDEF_EXTENDS])
1127                 parent = mono_class_get (image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]));
1128         interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount);
1129
1130         class = g_malloc0 (sizeof (MonoClass));
1131                            
1132         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
1133
1134         class->interfaces = interfaces;
1135         class->interface_count = icount;
1136
1137         class->name = name;
1138         class->name_space = nspace;
1139
1140         class->image = image;
1141         class->type_token = type_token;
1142         class->flags = cols [MONO_TYPEDEF_FLAGS];
1143
1144         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
1145                 class->unicode = 1;
1146         /* fixme: maybe we must set this on windows 
1147         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
1148                 class->unicode = 1;
1149         */
1150
1151         class->element_class = class;
1152
1153         /*g_print ("Init class %s\n", name);*/
1154
1155         mono_class_setup_parent (class, parent);
1156
1157         mono_class_setup_mono_type (class);
1158
1159         /*
1160          * Compute the field and method lists
1161          */
1162         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
1163         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
1164
1165         if (tt->rows > tidx){           
1166                 mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
1167                 class->field.last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
1168                 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
1169         } else {
1170                 class->field.last  = image->tables [MONO_TABLE_FIELD].rows;
1171                 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
1172         }
1173
1174         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
1175             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
1176                 class->field.count = class->field.last - class->field.first;
1177         else
1178                 class->field.count = 0;
1179
1180         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
1181                 class->method.count = class->method.last - class->method.first;
1182         else
1183                 class->method.count = 0;
1184
1185         /* reserve space to store vector pointer in arrays */
1186         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
1187                 class->instance_size += 2 * sizeof (gpointer);
1188                 g_assert (class->field.count == 0);
1189         }
1190
1191         if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
1192                 class->interface_id = mono_get_unique_iid (class);
1193
1194         /*class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &class->interface_count); */
1195
1196         if (class->enumtype)
1197                 class_compute_field_layout (class);
1198
1199         if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
1200                 class->nested_in = mono_class_create_from_typedef (image, type_token);
1201
1202         return class;
1203 }
1204
1205 MonoClass *
1206 mono_ptr_class_get (MonoType *type)
1207 {
1208         MonoClass *result;
1209         MonoClass *el_class;
1210         static GHashTable *ptr_hash = NULL;
1211
1212         if (!ptr_hash)
1213                 ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
1214         el_class = mono_class_from_mono_type (type);
1215         if ((result = g_hash_table_lookup (ptr_hash, el_class)))
1216                 return result;
1217         result = g_new0 (MonoClass, 1);
1218
1219         result->parent = NULL; /* no parent for PTR types */
1220         result->name = "System";
1221         result->name_space = "MonoPtrFakeClass";
1222         result->image = el_class->image;
1223         result->inited = TRUE;
1224         /* Can pointers get boxed? */
1225         result->instance_size = sizeof (gpointer);
1226         /*
1227          * baseval, diffval: need them to allow casting ?
1228          */
1229         result->element_class = el_class;
1230         result->enum_basetype = &result->element_class->byval_arg;
1231
1232         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
1233         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
1234         result->this_arg.byref = TRUE;
1235
1236         g_hash_table_insert (ptr_hash, el_class, result);
1237
1238         return result;
1239 }
1240
1241 MonoClass *
1242 mono_class_from_mono_type (MonoType *type)
1243 {
1244         switch (type->type) {
1245         case MONO_TYPE_OBJECT:
1246                 return mono_defaults.object_class;
1247         case MONO_TYPE_VOID:
1248                 return mono_defaults.void_class;
1249         case MONO_TYPE_BOOLEAN:
1250                 return mono_defaults.boolean_class;
1251         case MONO_TYPE_CHAR:
1252                 return mono_defaults.char_class;
1253         case MONO_TYPE_I1:
1254                 return mono_defaults.sbyte_class;
1255         case MONO_TYPE_U1:
1256                 return mono_defaults.byte_class;
1257         case MONO_TYPE_I2:
1258                 return mono_defaults.int16_class;
1259         case MONO_TYPE_U2:
1260                 return mono_defaults.uint16_class;
1261         case MONO_TYPE_I4:
1262                 return mono_defaults.int32_class;
1263         case MONO_TYPE_U4:
1264                 return mono_defaults.uint32_class;
1265         case MONO_TYPE_I:
1266                 return mono_defaults.int_class;
1267         case MONO_TYPE_U:
1268                 return mono_defaults.uint_class;
1269         case MONO_TYPE_I8:
1270                 return mono_defaults.int64_class;
1271         case MONO_TYPE_U8:
1272                 return mono_defaults.uint64_class;
1273         case MONO_TYPE_R4:
1274                 return mono_defaults.single_class;
1275         case MONO_TYPE_R8:
1276                 return mono_defaults.double_class;
1277         case MONO_TYPE_STRING:
1278                 return mono_defaults.string_class;
1279         case MONO_TYPE_ARRAY:
1280                 return mono_array_class_get (type->data.array->type, type->data.array->rank);
1281         case MONO_TYPE_PTR:
1282                 return mono_ptr_class_get (type->data.type);
1283         case MONO_TYPE_SZARRAY:
1284                 return mono_array_class_get (type->data.type, 1);
1285         case MONO_TYPE_CLASS:
1286         case MONO_TYPE_VALUETYPE:
1287                 return type->data.klass;
1288         default:
1289                 g_warning ("implement me %02x\n", type->type);
1290                 g_assert_not_reached ();
1291         }
1292         
1293         return NULL;
1294 }
1295
1296 /**
1297  * @image: context where the image is created
1298  * @type_spec:  typespec token
1299  */
1300 static MonoClass *
1301 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
1302 {
1303         MonoType *type;
1304         MonoClass *class;
1305
1306         type = mono_type_create_from_typespec (image, type_spec);
1307
1308         switch (type->type) {
1309         case MONO_TYPE_ARRAY:
1310                 class = mono_array_class_get (type->data.array->type, type->data.array->rank);
1311                 break;
1312         case MONO_TYPE_SZARRAY:
1313                 class = mono_array_class_get (type->data.type, 1);
1314                 break;
1315         case MONO_TYPE_PTR:
1316                 class = mono_class_from_mono_type (type->data.type);
1317                 break;
1318         default:
1319                 /* it seems any type can be stored in TypeSpec as well */
1320                 class = mono_class_from_mono_type (type);
1321                 break;
1322         }
1323
1324         mono_metadata_free_type (type);
1325         
1326         return class;
1327 }
1328
1329 /**
1330  * mono_array_class_get:
1331  * @element_type: element type 
1332  * @rank: the dimension of the array class
1333  *
1334  * Returns: a class object describing the array with element type @element_type and 
1335  * dimension @rank. 
1336  */
1337 MonoClass *
1338 mono_array_class_get (MonoType *element_type, guint32 rank)
1339 {
1340         MonoClass *eclass;
1341         MonoImage *image;
1342         MonoClass *class;
1343         MonoClass *parent = NULL;
1344         GSList *list;
1345         int rnum = 0, nsize;
1346
1347         eclass = mono_class_from_mono_type (element_type);
1348         g_assert (rank <= 255);
1349
1350         parent = mono_defaults.array_class;
1351
1352         if (!parent->inited)
1353                 mono_class_init (parent);
1354
1355         image = eclass->image;
1356
1357         if ((list = g_hash_table_lookup (image->array_cache, element_type))) {
1358                 for (; list; list = list->next) {
1359                         class = list->data;
1360                         if (class->rank == rank)
1361                                 return class;
1362                 }
1363         }
1364         
1365         class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
1366
1367         class->image = image;
1368         class->name_space = eclass->name_space;
1369         nsize = strlen (eclass->name);
1370         class->name = g_malloc (nsize + 2 + rank);
1371         memcpy (class->name, eclass->name, nsize);
1372         class->name [nsize] = '[';
1373         if (rank > 1)
1374                 memset (class->name + nsize + 1, ',', rank - 1);
1375         class->name [nsize + rank] = ']';
1376         class->name [nsize + rank + 1] = 0;
1377         class->type_token = 0;
1378         class->flags = TYPE_ATTRIBUTE_CLASS;
1379         class->parent = parent;
1380         class->instance_size = mono_class_instance_size (class->parent);
1381         class->class_size = 0;
1382         class->vtable_size = parent->vtable_size;
1383         class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
1384         mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
1385
1386         class->rank = rank;
1387         class->element_class = eclass;
1388         if (rank > 1) {
1389                 MonoArrayType *at = g_new0 (MonoArrayType, 1);
1390                 class->byval_arg.type = MONO_TYPE_ARRAY;
1391                 class->byval_arg.data.array = at;
1392                 at->type = &eclass->byval_arg;
1393                 at->rank = rank;
1394                 /* FIXME: complete.... */
1395         } else {
1396                 /* FIXME: this is not correct. the lbound could be >0 */
1397                 class->byval_arg.type = MONO_TYPE_SZARRAY;
1398                 class->byval_arg.data.type = &eclass->byval_arg;
1399         }
1400         class->this_arg = class->byval_arg;
1401         class->this_arg.byref = 1;
1402
1403         list = g_slist_append (list, class);
1404         g_hash_table_insert (image->array_cache, &class->element_class->byval_arg, list);
1405         return class;
1406 }
1407
1408 /**
1409  * mono_class_instance_size:
1410  * @klass: a class 
1411  * 
1412  * Returns: the size of an object instance
1413  */
1414 gint32
1415 mono_class_instance_size (MonoClass *klass)
1416 {
1417         
1418         if (!klass->size_inited)
1419                 mono_class_init (klass);
1420
1421         return klass->instance_size;
1422 }
1423
1424 /**
1425  * mono_class_native_size:
1426  * @klass: a class 
1427  * 
1428  * Returns: the native size of an object instance (when marshaled 
1429  * to unmanaged code) 
1430  */
1431 gint32
1432 mono_class_native_size (MonoClass *klass, guint32 *align)
1433 {
1434         
1435         if (!klass->marshal_info)
1436                 mono_marshal_load_type_info (klass);
1437
1438         if (align)
1439                 *align = klass->min_align;
1440
1441         return klass->marshal_info->native_size;
1442 }
1443
1444 /**
1445  * mono_class_min_align:
1446  * @klass: a class 
1447  * 
1448  * Returns: minimm alignment requirements 
1449  */
1450 gint32
1451 mono_class_min_align (MonoClass *klass)
1452 {
1453         
1454         if (!klass->size_inited)
1455                 mono_class_init (klass);
1456
1457         return klass->min_align;
1458 }
1459
1460 /**
1461  * mono_class_value_size:
1462  * @klass: a class 
1463  *
1464  * This function is used for value types, and return the
1465  * space and the alignment to store that kind of value object.
1466  *
1467  * Returns: the size of a value of kind @klass
1468  */
1469 gint32
1470 mono_class_value_size      (MonoClass *klass, guint32 *align)
1471 {
1472         gint32 size;
1473
1474         /* fixme: check disable, because we still have external revereces to
1475          * mscorlib and Dummy Objects 
1476          */
1477         /*g_assert (klass->valuetype);*/
1478
1479         size = mono_class_instance_size (klass) - sizeof (MonoObject);
1480
1481         if (align)
1482                 *align = klass->min_align;
1483
1484         return size;
1485 }
1486
1487 /**
1488  * mono_class_data_size:
1489  * @klass: a class 
1490  * 
1491  * Returns: the size of the static class data
1492  */
1493 gint32
1494 mono_class_data_size (MonoClass *klass)
1495 {
1496         
1497         if (!klass->inited)
1498                 mono_class_init (klass);
1499
1500         return klass->class_size;
1501 }
1502
1503 /*
1504  * Auxiliary routine to mono_class_get_field
1505  *
1506  * Takes a field index instead of a field token.
1507  */
1508 static MonoClassField *
1509 mono_class_get_field_idx (MonoClass *class, int idx)
1510 {
1511         if (class->field.count){
1512                 if ((idx >= class->field.first) && (idx < class->field.last)){
1513                         return &class->fields [idx - class->field.first];
1514                 }
1515         }
1516
1517         if (!class->parent)
1518                 return NULL;
1519         
1520         return mono_class_get_field_idx (class->parent, idx);
1521 }
1522
1523 /**
1524  * mono_class_get_field:
1525  * @class: the class to lookup the field.
1526  * @field_token: the field token
1527  *
1528  * Returns: A MonoClassField representing the type and offset of
1529  * the field, or a NULL value if the field does not belong to this
1530  * class.
1531  */
1532 MonoClassField *
1533 mono_class_get_field (MonoClass *class, guint32 field_token)
1534 {
1535         int idx = mono_metadata_token_index (field_token);
1536
1537         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
1538
1539         return mono_class_get_field_idx (class, idx - 1);
1540 }
1541
1542 MonoClassField *
1543 mono_class_get_field_from_name (MonoClass *klass, const char *name)
1544 {
1545         int i;
1546
1547         while (klass) {
1548                 for (i = 0; i < klass->field.count; ++i) {
1549                         if (strcmp (name, klass->fields [i].name) == 0)
1550                                 return &klass->fields [i];
1551                 }
1552                 klass = klass->parent;
1553         }
1554         return NULL;
1555 }
1556
1557 MonoProperty*
1558 mono_class_get_property_from_name (MonoClass *klass, const char *name)
1559 {
1560         int i;
1561
1562         while (klass) {
1563                 for (i = 0; i < klass->property.count; ++i) {
1564                         if (strcmp (name, klass->properties [i].name) == 0)
1565                                 return &klass->properties [i];
1566                 }
1567                 klass = klass->parent;
1568         }
1569         return NULL;
1570 }
1571
1572 /**
1573  * mono_class_get:
1574  * @image: the image where the class resides
1575  * @type_token: the token for the class
1576  * @at: an optional pointer to return the array element type
1577  *
1578  * Returns: the MonoClass that represents @type_token in @image
1579  */
1580 MonoClass *
1581 mono_class_get (MonoImage *image, guint32 type_token)
1582 {
1583         MonoClass *class;
1584
1585         switch (type_token & 0xff000000){
1586         case MONO_TOKEN_TYPE_DEF:
1587                 class = mono_class_create_from_typedef (image, type_token);
1588                 break;          
1589         case MONO_TOKEN_TYPE_REF:
1590                 class = mono_class_from_typeref (image, type_token);
1591                 break;
1592         case MONO_TOKEN_TYPE_SPEC:
1593                 class = mono_class_create_from_typespec (image, type_token);
1594                 break;
1595         default:
1596                 g_warning ("unknown token type %x", type_token & 0xff000000);
1597                 g_assert_not_reached ();
1598         }
1599
1600         if (!class)
1601                 g_warning ("Could not load class from token 0x%08x in %s", type_token, image->name);
1602
1603         return class;
1604 }
1605
1606 MonoClass *
1607 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
1608 {
1609         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
1610         guint32 cols [MONO_TYPEDEF_SIZE];
1611         const char *n;
1612         const char *nspace;
1613         guint32 i, visib;
1614
1615         /* add a cache if needed */
1616         for (i = 1; i <= t->rows; ++i) {
1617                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
1618                 /* nested types are accessed from the nesting name */
1619                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1620                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
1621                         continue;
1622                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1623                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1624                 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
1625                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
1626         }
1627         return NULL;
1628 }
1629
1630 MonoClass *
1631 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
1632 {
1633         GHashTable *nspace_table;
1634         guint32 token;
1635
1636         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
1637         if (!nspace_table)
1638                 return 0;
1639         token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
1640         
1641         if (!token) {
1642                 /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/
1643                 return NULL;
1644         }
1645
1646         token = MONO_TOKEN_TYPE_DEF | token;
1647
1648         return mono_class_get (image, token);
1649 }
1650
1651 /**
1652  * mono_array_element_size:
1653  * @ac: pointer to a #MonoArrayClass
1654  *
1655  * Returns: the size of single array element.
1656  */
1657 gint32
1658 mono_array_element_size (MonoClass *ac)
1659 {
1660         if (ac->element_class->valuetype)
1661                 return mono_class_instance_size (ac->element_class) - sizeof (MonoObject);
1662         else
1663                 return sizeof (gpointer);
1664 }
1665
1666 gpointer
1667 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
1668 {
1669         switch (token & 0xff000000) {
1670         case MONO_TOKEN_TYPE_DEF:
1671         case MONO_TOKEN_TYPE_REF: {
1672                 MonoClass *class;
1673                 if (handle_class)
1674                         *handle_class = mono_defaults.typehandle_class;
1675                 class = mono_class_get (image, token);
1676                 mono_class_init (class);
1677                 /* We return a MonoType* as handle */
1678                 return &class->byval_arg;
1679         }
1680         case MONO_TOKEN_TYPE_SPEC: {
1681                 MonoClass *class;
1682                 if (handle_class)
1683                         *handle_class = mono_defaults.typehandle_class;
1684                 class = mono_class_create_from_typespec (image, token);
1685                 mono_class_init (class);
1686                 return &class->byval_arg;
1687         }
1688         case MONO_TOKEN_FIELD_DEF: {
1689                 MonoClass *class;
1690                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
1691                 class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type);
1692                 mono_class_init (class);
1693                 if (handle_class)
1694                                 *handle_class = mono_class_from_name (mono_defaults.corlib, "System", "RuntimeFieldHandle");
1695                 return mono_class_get_field (class, token);
1696         }
1697         case MONO_TOKEN_METHOD_DEF:
1698         case MONO_TOKEN_MEMBER_REF:
1699         default:
1700                 g_warning ("Unknown token 0x%08x in ldtoken", token);
1701                 break;
1702         }
1703         return NULL;
1704 }
1705