2007-09-12 Marek Safar <marek.safar@gmail.com>
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * (C) 2001 Ximian, Inc.
10  */
11
12 #include <config.h>
13 #include <glib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <ctype.h>
17 #ifdef HAVE_SYS_TIME_H
18 #include <sys/time.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #if defined (PLATFORM_WIN32)
24 #include <stdlib.h>
25 #endif
26
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/threads.h>
29 #include <mono/metadata/threads-types.h>
30 #include <mono/metadata/threadpool.h>
31 #include <mono/metadata/monitor.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/assembly.h>
34 #include <mono/metadata/tabledefs.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/file-io.h>
37 #include <mono/metadata/console-io.h>
38 #include <mono/metadata/socket-io.h>
39 #include <mono/metadata/mono-endian.h>
40 #include <mono/metadata/tokentype.h>
41 #include <mono/metadata/domain-internals.h>
42 #include <mono/metadata/metadata-internals.h>
43 #include <mono/metadata/class-internals.h>
44 #include <mono/metadata/marshal.h>
45 #include <mono/metadata/gc-internal.h>
46 #include <mono/metadata/mono-gc.h>
47 #include <mono/metadata/rand.h>
48 #include <mono/metadata/sysmath.h>
49 #include <mono/metadata/string-icalls.h>
50 #include <mono/metadata/debug-helpers.h>
51 #include <mono/metadata/process.h>
52 #include <mono/metadata/environment.h>
53 #include <mono/metadata/profiler-private.h>
54 #include <mono/metadata/locales.h>
55 #include <mono/metadata/filewatcher.h>
56 #include <mono/metadata/char-conversions.h>
57 #include <mono/metadata/security.h>
58 #include <mono/metadata/mono-config.h>
59 #include <mono/metadata/cil-coff.h>
60 #include <mono/metadata/security-manager.h>
61 #include <mono/metadata/security-core-clr.h>
62 #include <mono/io-layer/io-layer.h>
63 #include <mono/utils/strtod.h>
64 #include <mono/utils/monobitset.h>
65
66 #if defined (PLATFORM_WIN32)
67 #include <windows.h>
68 #include <shlobj.h>
69 #endif
70 #include "decimal.h"
71
72 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
73
74 static MonoArray*
75 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
76
77 static inline MonoBoolean
78 is_generic_parameter (MonoType *type)
79 {
80         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
81 }
82
83 /*
84  * We expect a pointer to a char, not a string
85  */
86 static gboolean
87 mono_double_ParseImpl (char *ptr, double *result)
88 {
89         gchar *endptr = NULL;
90         *result = 0.0;
91
92         MONO_ARCH_SAVE_REGS;
93
94 #ifdef __arm__
95         if (*ptr)
96                 *result = strtod (ptr, &endptr);
97 #else
98         if (*ptr)
99                 *result = bsd_strtod (ptr, &endptr);
100 #endif
101
102         if (!*ptr || (endptr && *endptr))
103                 return FALSE;
104         
105         return TRUE;
106 }
107
108 static MonoClass *
109 mono_class_get_throw (MonoImage *image, guint32 type_token)
110 {
111         MonoClass *class = mono_class_get (image, type_token);
112         MonoLoaderError *error;
113         MonoException *ex;
114         
115         if (class != NULL)
116                 return class;
117
118         error = mono_loader_get_last_error ();
119         g_assert (error != NULL);
120         
121         ex = mono_loader_error_prepare_exception (error);
122         mono_raise_exception (ex);
123         return NULL;
124 }
125
126 static MonoObject *
127 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
128 {
129         MonoClass *ac;
130         MonoArray *ao;
131         gint32 esize;
132         gpointer *ea;
133
134         MONO_ARCH_SAVE_REGS;
135
136         ao = (MonoArray *)this;
137         ac = (MonoClass *)ao->obj.vtable->klass;
138
139         esize = mono_array_element_size (ac);
140         ea = (gpointer*)((char*)ao->vector + (pos * esize));
141
142         if (ac->element_class->valuetype)
143                 return mono_value_box (this->vtable->domain, ac->element_class, ea);
144         else
145                 return *ea;
146 }
147
148 static MonoObject *
149 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
150 {
151         MonoClass *ac, *ic;
152         MonoArray *ao, *io;
153         gint32 i, pos, *ind;
154
155         MONO_ARCH_SAVE_REGS;
156
157         MONO_CHECK_ARG_NULL (idxs);
158
159         io = (MonoArray *)idxs;
160         ic = (MonoClass *)io->obj.vtable->klass;
161         
162         ao = (MonoArray *)this;
163         ac = (MonoClass *)ao->obj.vtable->klass;
164
165         g_assert (ic->rank == 1);
166         if (io->bounds != NULL || io->max_length !=  ac->rank)
167                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
168
169         ind = (gint32 *)io->vector;
170
171         if (ao->bounds == NULL) {
172                 if (*ind < 0 || *ind >= ao->max_length)
173                         mono_raise_exception (mono_get_exception_index_out_of_range ());
174
175                 return ves_icall_System_Array_GetValueImpl (this, *ind);
176         }
177         
178         for (i = 0; i < ac->rank; i++)
179                 if ((ind [i] < ao->bounds [i].lower_bound) ||
180                     (ind [i] >= ao->bounds [i].length + ao->bounds [i].lower_bound))
181                         mono_raise_exception (mono_get_exception_index_out_of_range ());
182
183         pos = ind [0] - ao->bounds [0].lower_bound;
184         for (i = 1; i < ac->rank; i++)
185                 pos = pos*ao->bounds [i].length + ind [i] - 
186                         ao->bounds [i].lower_bound;
187
188         return ves_icall_System_Array_GetValueImpl (this, pos);
189 }
190
191 static void
192 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
193 {
194         MonoClass *ac, *vc, *ec;
195         gint32 esize, vsize;
196         gpointer *ea, *va;
197         int et, vt;
198
199         guint64 u64 = 0;
200         gint64 i64 = 0;
201         gdouble r64 = 0;
202
203         MONO_ARCH_SAVE_REGS;
204
205         if (value)
206                 vc = value->vtable->klass;
207         else
208                 vc = NULL;
209
210         ac = this->obj.vtable->klass;
211         ec = ac->element_class;
212
213         esize = mono_array_element_size (ac);
214         ea = (gpointer*)((char*)this->vector + (pos * esize));
215         va = (gpointer*)((char*)value + sizeof (MonoObject));
216
217         if (!value) {
218                 memset (ea, 0,  esize);
219                 return;
220         }
221
222 #define NO_WIDENING_CONVERSION G_STMT_START{\
223         mono_raise_exception (mono_get_exception_argument ( \
224                 "value", "not a widening conversion")); \
225 }G_STMT_END
226
227 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
228         if (esize < vsize + (extra)) \
229                 mono_raise_exception (mono_get_exception_argument ( \
230                         "value", "not a widening conversion")); \
231 }G_STMT_END
232
233 #define INVALID_CAST G_STMT_START{\
234         mono_raise_exception (mono_get_exception_invalid_cast ()); \
235 }G_STMT_END
236
237         /* Check element (destination) type. */
238         switch (ec->byval_arg.type) {
239         case MONO_TYPE_STRING:
240                 switch (vc->byval_arg.type) {
241                 case MONO_TYPE_STRING:
242                         break;
243                 default:
244                         INVALID_CAST;
245                 }
246                 break;
247         case MONO_TYPE_BOOLEAN:
248                 switch (vc->byval_arg.type) {
249                 case MONO_TYPE_BOOLEAN:
250                         break;
251                 case MONO_TYPE_CHAR:
252                 case MONO_TYPE_U1:
253                 case MONO_TYPE_U2:
254                 case MONO_TYPE_U4:
255                 case MONO_TYPE_U8:
256                 case MONO_TYPE_I1:
257                 case MONO_TYPE_I2:
258                 case MONO_TYPE_I4:
259                 case MONO_TYPE_I8:
260                 case MONO_TYPE_R4:
261                 case MONO_TYPE_R8:
262                         NO_WIDENING_CONVERSION;
263                 default:
264                         INVALID_CAST;
265                 }
266                 break;
267         }
268
269         if (!ec->valuetype) {
270                 if (!mono_object_isinst (value, ec))
271                         INVALID_CAST;
272                 *ea = (gpointer)value;
273                 return;
274         }
275
276         if (mono_object_isinst (value, ec)) {
277                 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
278                 return;
279         }
280
281         if (!vc->valuetype)
282                 INVALID_CAST;
283
284         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
285
286         et = ec->byval_arg.type;
287         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
288                 et = ec->byval_arg.data.klass->enum_basetype->type;
289
290         vt = vc->byval_arg.type;
291         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
292                 vt = vc->byval_arg.data.klass->enum_basetype->type;
293
294 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
295         switch (vt) { \
296         case MONO_TYPE_U1: \
297         case MONO_TYPE_U2: \
298         case MONO_TYPE_U4: \
299         case MONO_TYPE_U8: \
300         case MONO_TYPE_CHAR: \
301                 CHECK_WIDENING_CONVERSION(0); \
302                 *(etype *) ea = (etype) u64; \
303                 return; \
304         /* You can't assign a signed value to an unsigned array. */ \
305         case MONO_TYPE_I1: \
306         case MONO_TYPE_I2: \
307         case MONO_TYPE_I4: \
308         case MONO_TYPE_I8: \
309         /* You can't assign a floating point number to an integer array. */ \
310         case MONO_TYPE_R4: \
311         case MONO_TYPE_R8: \
312                 NO_WIDENING_CONVERSION; \
313         } \
314 }G_STMT_END
315
316 #define ASSIGN_SIGNED(etype) G_STMT_START{\
317         switch (vt) { \
318         case MONO_TYPE_I1: \
319         case MONO_TYPE_I2: \
320         case MONO_TYPE_I4: \
321         case MONO_TYPE_I8: \
322                 CHECK_WIDENING_CONVERSION(0); \
323                 *(etype *) ea = (etype) i64; \
324                 return; \
325         /* You can assign an unsigned value to a signed array if the array's */ \
326         /* element size is larger than the value size. */ \
327         case MONO_TYPE_U1: \
328         case MONO_TYPE_U2: \
329         case MONO_TYPE_U4: \
330         case MONO_TYPE_U8: \
331         case MONO_TYPE_CHAR: \
332                 CHECK_WIDENING_CONVERSION(1); \
333                 *(etype *) ea = (etype) u64; \
334                 return; \
335         /* You can't assign a floating point number to an integer array. */ \
336         case MONO_TYPE_R4: \
337         case MONO_TYPE_R8: \
338                 NO_WIDENING_CONVERSION; \
339         } \
340 }G_STMT_END
341
342 #define ASSIGN_REAL(etype) G_STMT_START{\
343         switch (vt) { \
344         case MONO_TYPE_R4: \
345         case MONO_TYPE_R8: \
346                 CHECK_WIDENING_CONVERSION(0); \
347                 *(etype *) ea = (etype) r64; \
348                 return; \
349         /* All integer values fit into a floating point array, so we don't */ \
350         /* need to CHECK_WIDENING_CONVERSION here. */ \
351         case MONO_TYPE_I1: \
352         case MONO_TYPE_I2: \
353         case MONO_TYPE_I4: \
354         case MONO_TYPE_I8: \
355                 *(etype *) ea = (etype) i64; \
356                 return; \
357         case MONO_TYPE_U1: \
358         case MONO_TYPE_U2: \
359         case MONO_TYPE_U4: \
360         case MONO_TYPE_U8: \
361         case MONO_TYPE_CHAR: \
362                 *(etype *) ea = (etype) u64; \
363                 return; \
364         } \
365 }G_STMT_END
366
367         switch (vt) {
368         case MONO_TYPE_U1:
369                 u64 = *(guint8 *) va;
370                 break;
371         case MONO_TYPE_U2:
372                 u64 = *(guint16 *) va;
373                 break;
374         case MONO_TYPE_U4:
375                 u64 = *(guint32 *) va;
376                 break;
377         case MONO_TYPE_U8:
378                 u64 = *(guint64 *) va;
379                 break;
380         case MONO_TYPE_I1:
381                 i64 = *(gint8 *) va;
382                 break;
383         case MONO_TYPE_I2:
384                 i64 = *(gint16 *) va;
385                 break;
386         case MONO_TYPE_I4:
387                 i64 = *(gint32 *) va;
388                 break;
389         case MONO_TYPE_I8:
390                 i64 = *(gint64 *) va;
391                 break;
392         case MONO_TYPE_R4:
393                 r64 = *(gfloat *) va;
394                 break;
395         case MONO_TYPE_R8:
396                 r64 = *(gdouble *) va;
397                 break;
398         case MONO_TYPE_CHAR:
399                 u64 = *(guint16 *) va;
400                 break;
401         case MONO_TYPE_BOOLEAN:
402                 /* Boolean is only compatible with itself. */
403                 switch (et) {
404                 case MONO_TYPE_CHAR:
405                 case MONO_TYPE_U1:
406                 case MONO_TYPE_U2:
407                 case MONO_TYPE_U4:
408                 case MONO_TYPE_U8:
409                 case MONO_TYPE_I1:
410                 case MONO_TYPE_I2:
411                 case MONO_TYPE_I4:
412                 case MONO_TYPE_I8:
413                 case MONO_TYPE_R4:
414                 case MONO_TYPE_R8:
415                         NO_WIDENING_CONVERSION;
416                 default:
417                         INVALID_CAST;
418                 }
419                 break;
420         }
421
422         /* If we can't do a direct copy, let's try a widening conversion. */
423         switch (et) {
424         case MONO_TYPE_CHAR:
425                 ASSIGN_UNSIGNED (guint16);
426         case MONO_TYPE_U1:
427                 ASSIGN_UNSIGNED (guint8);
428         case MONO_TYPE_U2:
429                 ASSIGN_UNSIGNED (guint16);
430         case MONO_TYPE_U4:
431                 ASSIGN_UNSIGNED (guint32);
432         case MONO_TYPE_U8:
433                 ASSIGN_UNSIGNED (guint64);
434         case MONO_TYPE_I1:
435                 ASSIGN_SIGNED (gint8);
436         case MONO_TYPE_I2:
437                 ASSIGN_SIGNED (gint16);
438         case MONO_TYPE_I4:
439                 ASSIGN_SIGNED (gint32);
440         case MONO_TYPE_I8:
441                 ASSIGN_SIGNED (gint64);
442         case MONO_TYPE_R4:
443                 ASSIGN_REAL (gfloat);
444         case MONO_TYPE_R8:
445                 ASSIGN_REAL (gdouble);
446         }
447
448         INVALID_CAST;
449         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
450         return;
451
452 #undef INVALID_CAST
453 #undef NO_WIDENING_CONVERSION
454 #undef CHECK_WIDENING_CONVERSION
455 #undef ASSIGN_UNSIGNED
456 #undef ASSIGN_SIGNED
457 #undef ASSIGN_REAL
458 }
459
460 static void 
461 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
462                                  MonoArray *idxs)
463 {
464         MonoClass *ac, *ic;
465         gint32 i, pos, *ind;
466
467         MONO_ARCH_SAVE_REGS;
468
469         MONO_CHECK_ARG_NULL (idxs);
470
471         ic = idxs->obj.vtable->klass;
472         ac = this->obj.vtable->klass;
473
474         g_assert (ic->rank == 1);
475         if (idxs->bounds != NULL || idxs->max_length != ac->rank)
476                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
477
478         ind = (gint32 *)idxs->vector;
479
480         if (this->bounds == NULL) {
481                 if (*ind < 0 || *ind >= this->max_length)
482                         mono_raise_exception (mono_get_exception_index_out_of_range ());
483
484                 ves_icall_System_Array_SetValueImpl (this, value, *ind);
485                 return;
486         }
487         
488         for (i = 0; i < ac->rank; i++)
489                 if ((ind [i] < this->bounds [i].lower_bound) ||
490                     (ind [i] >= this->bounds [i].length + this->bounds [i].lower_bound))
491                         mono_raise_exception (mono_get_exception_index_out_of_range ());
492
493         pos = ind [0] - this->bounds [0].lower_bound;
494         for (i = 1; i < ac->rank; i++)
495                 pos = pos * this->bounds [i].length + ind [i] - 
496                         this->bounds [i].lower_bound;
497
498         ves_icall_System_Array_SetValueImpl (this, value, pos);
499 }
500
501 static MonoArray *
502 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
503 {
504         MonoClass *aklass;
505         MonoArray *array;
506         guint32 *sizes, i;
507         gboolean bounded = FALSE;
508
509         MONO_ARCH_SAVE_REGS;
510
511         MONO_CHECK_ARG_NULL (type);
512         MONO_CHECK_ARG_NULL (lengths);
513
514         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
515         if (bounds)
516                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
517
518         for (i = 0; i < mono_array_length (lengths); i++)
519                 if (mono_array_get (lengths, gint32, i) < 0)
520                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
521
522         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
523                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
524                 bounded = TRUE;
525         else
526                 bounded = FALSE;
527
528         aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
529
530         sizes = alloca (aklass->rank * sizeof(guint32) * 2);
531         for (i = 0; i < aklass->rank; ++i) {
532                 sizes [i] = mono_array_get (lengths, guint32, i);
533                 if (bounds)
534                         sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
535                 else
536                         sizes [i + aklass->rank] = 0;
537         }
538
539         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
540
541         return array;
542 }
543
544 static gint32 
545 ves_icall_System_Array_GetRank (MonoObject *this)
546 {
547         MONO_ARCH_SAVE_REGS;
548
549         return this->vtable->klass->rank;
550 }
551
552 static gint32
553 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
554 {
555         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
556
557         MONO_ARCH_SAVE_REGS;
558
559         if ((dimension < 0) || (dimension >= rank))
560                 mono_raise_exception (mono_get_exception_index_out_of_range ());
561         
562         if (this->bounds == NULL)
563                 return this->max_length;
564         
565         return this->bounds [dimension].length;
566 }
567
568 static gint32
569 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
570 {
571         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
572
573         MONO_ARCH_SAVE_REGS;
574
575         if ((dimension < 0) || (dimension >= rank))
576                 mono_raise_exception (mono_get_exception_index_out_of_range ());
577         
578         if (this->bounds == NULL)
579                 return 0;
580         
581         return this->bounds [dimension].lower_bound;
582 }
583
584 static void
585 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
586 {
587         int sz = mono_array_element_size (mono_object_class (arr));
588         memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
589 }
590
591 static gboolean
592 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
593 {
594         int element_size;
595         void * dest_addr;
596         void * source_addr;
597         MonoClass *src_class;
598         MonoClass *dest_class;
599         int i;
600
601         MONO_ARCH_SAVE_REGS;
602
603         if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
604                 return FALSE;
605
606         if (source->bounds || dest->bounds)
607                 return FALSE;
608
609         if ((dest_idx + length > mono_array_length (dest)) ||
610                 (source_idx + length > mono_array_length (source)))
611                 return FALSE;
612
613         src_class = source->obj.vtable->klass->element_class;
614         dest_class = dest->obj.vtable->klass->element_class;
615
616         /*
617          * Handle common cases.
618          */
619
620         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
621         if (src_class == mono_defaults.object_class && dest_class->valuetype) {
622                 int has_refs = dest_class->has_references;
623                 for (i = source_idx; i < source_idx + length; ++i) {
624                         MonoObject *elem = mono_array_get (source, MonoObject*, i);
625                         if (elem && !mono_object_isinst (elem, dest_class))
626                                 return FALSE;
627                 }
628
629                 element_size = mono_array_element_size (dest->obj.vtable->klass);
630                 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
631                 for (i = 0; i < length; ++i) {
632                         MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
633                         void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
634                         if (!elem)
635                                 continue;
636                         if (has_refs)
637                                 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
638                         else
639                                 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
640                 }
641                 return TRUE;
642         }
643
644         /* Check if we're copying a char[] <==> (u)short[] */
645         if (src_class != dest_class) {
646                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
647                         return FALSE;
648
649                 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
650                         ;
651                 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
652                 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
653                         for (i = source_idx; i < source_idx + length; ++i) {
654                                 MonoObject *elem = mono_array_get (source, MonoObject*, i);
655                                 if (elem && !mono_object_isinst (elem, dest_class))
656                                         return FALSE;
657                         }
658                 else
659                         return FALSE;
660         }
661
662         if (dest_class->valuetype) {
663                 element_size = mono_array_element_size (source->obj.vtable->klass);
664                 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
665                 if (dest_class->has_references) {
666                         mono_value_copy_array (dest, dest_idx, source_addr, length);
667                 } else {
668                         dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
669                         memmove (dest_addr, source_addr, element_size * length);
670                 }
671         } else {
672                 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
673         }
674
675         return TRUE;
676 }
677
678 static void
679 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
680 {
681         MonoClass *ac;
682         MonoArray *ao;
683         gint32 esize;
684         gpointer *ea;
685
686         MONO_ARCH_SAVE_REGS;
687
688         ao = (MonoArray *)this;
689         ac = (MonoClass *)ao->obj.vtable->klass;
690
691         esize = mono_array_element_size (ac);
692         ea = (gpointer*)((char*)ao->vector + (pos * esize));
693
694         memcpy (value, ea, esize);
695 }
696
697 static void
698 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
699 {
700         MonoClass *ac;
701         MonoArray *ao;
702         gint32 esize;
703         gpointer *ea;
704
705         MONO_ARCH_SAVE_REGS;
706
707         ao = (MonoArray *)this;
708         ac = (MonoClass *)ao->obj.vtable->klass;
709
710         esize = mono_array_element_size (ac);
711         ea = (gpointer*)((char*)ao->vector + (pos * esize));
712
713         memcpy (ea, value, esize);
714 }
715
716 static void
717 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
718 {
719         MonoClass *klass = array->obj.vtable->klass;
720         guint32 size = mono_array_element_size (klass);
721
722         size *= array->max_length;
723
724 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
725 #define SWAP(n) {\
726         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
727         guint ## n *src = (guint ## n *) field_handle->data; \
728         guint ## n *end = (guint ## n *)((char*)src + size); \
729 \
730         for (; src < end; data++, src++) { \
731                 *data = read ## n (src); \
732         } \
733 }
734
735         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
736
737         switch (mono_type_get_underlying_type (&klass->element_class->byval_arg)->type) {
738         case MONO_TYPE_CHAR:
739         case MONO_TYPE_I2:
740         case MONO_TYPE_U2:
741                 SWAP (16);
742                 break;
743         case MONO_TYPE_I4:
744         case MONO_TYPE_U4:
745         case MONO_TYPE_R4:
746                 SWAP (32);
747                 break;
748         case MONO_TYPE_I8:
749         case MONO_TYPE_U8:
750         case MONO_TYPE_R8:
751                 SWAP (64);
752                 break;
753         default:
754                 memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
755                 break;
756         }
757 #else
758         memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
759 #ifdef ARM_FPU_FPA
760         if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
761                 gint i;
762                 double tmp;
763                 double *data = (double*)mono_array_addr (array, double, 0);
764
765                 for (i = 0; i < size; i++, data++) {
766                         readr8 (data, &tmp);
767                         *data = tmp;
768                 }
769         }
770 #endif
771 #endif
772 }
773
774 static gint
775 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
776 {
777         MONO_ARCH_SAVE_REGS;
778
779         return offsetof (MonoString, chars);
780 }
781
782 static MonoObject *
783 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
784 {
785         MONO_ARCH_SAVE_REGS;
786
787         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
788                 return obj;
789         else
790                 return mono_object_clone (obj);
791 }
792
793 static void
794 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
795 {
796         MonoClass *klass;
797
798         MONO_ARCH_SAVE_REGS;
799
800         MONO_CHECK_ARG_NULL (handle);
801
802         klass = mono_class_from_mono_type (handle);
803         MONO_CHECK_ARG (handle, klass);
804
805         /* This will call the type constructor */
806         if (! (klass->flags & TYPE_ATTRIBUTE_INTERFACE))
807                 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
808 }
809
810 static void
811 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
812 {
813         MONO_ARCH_SAVE_REGS;
814
815         mono_image_check_for_module_cctor (image);
816         if (image->has_module_cctor) {
817                 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
818                 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
819         }
820 }
821
822 static MonoObject *
823 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
824 {
825         MONO_ARCH_SAVE_REGS;
826
827         return mono_object_clone (this);
828 }
829
830 static gint32
831 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
832 {
833         MonoClass *klass;
834         MonoObject **values = NULL;
835         MonoObject *o;
836         int count = 0;
837         gint32 result = 0;
838         MonoClassField* field;
839         gpointer iter;
840
841         MONO_ARCH_SAVE_REGS;
842
843         klass = mono_object_class (this);
844
845         if (mono_class_num_fields (klass) == 0)
846                 return mono_object_hash (this);
847
848         /*
849          * Compute the starting value of the hashcode for fields of primitive
850          * types, and return the remaining fields in an array to the managed side.
851          * This way, we can avoid costly reflection operations in managed code.
852          */
853         iter = NULL;
854         while ((field = mono_class_get_fields (klass, &iter))) {
855                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
856                         continue;
857                 if (mono_field_is_deleted (field))
858                         continue;
859                 /* FIXME: Add more types */
860                 switch (field->type->type) {
861                 case MONO_TYPE_I4:
862                         result ^= *(gint32*)((guint8*)this + field->offset);
863                         break;
864                 case MONO_TYPE_STRING: {
865                         MonoString *s;
866                         s = *(MonoString**)((guint8*)this + field->offset);
867                         if (s != NULL)
868                                 result ^= mono_string_hash (s);
869                         break;
870                 }
871                 default:
872                         if (!values)
873                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
874                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
875                         values [count++] = o;
876                 }
877         }
878
879         if (values) {
880                 int i;
881                 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
882                 for (i = 0; i < count; ++i)
883                         mono_array_setref (*fields, i, values [i]);
884         } else {
885                 *fields = NULL;
886         }
887         return result;
888 }
889
890 static MonoBoolean
891 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
892 {
893         MonoClass *klass;
894         MonoObject **values = NULL;
895         MonoObject *o;
896         MonoClassField* field;
897         gpointer iter;
898         int count = 0;
899
900         MONO_ARCH_SAVE_REGS;
901
902         MONO_CHECK_ARG_NULL (that);
903
904         if (this->vtable != that->vtable)
905                 return FALSE;
906
907         klass = mono_object_class (this);
908
909         /*
910          * Do the comparison for fields of primitive type and return a result if
911          * possible. Otherwise, return the remaining fields in an array to the 
912          * managed side. This way, we can avoid costly reflection operations in 
913          * managed code.
914          */
915         *fields = NULL;
916         iter = NULL;
917         while ((field = mono_class_get_fields (klass, &iter))) {
918                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
919                         continue;
920                 if (mono_field_is_deleted (field))
921                         continue;
922                 /* FIXME: Add more types */
923                 switch (field->type->type) {
924                 case MONO_TYPE_I4:
925                         if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
926                                 return FALSE;
927                         break;
928                 case MONO_TYPE_STRING: {
929                         MonoString *s1, *s2;
930                         guint32 s1len, s2len;
931                         s1 = *(MonoString**)((guint8*)this + field->offset);
932                         s2 = *(MonoString**)((guint8*)that + field->offset);
933                         if (s1 == s2)
934                                 break;
935                         if ((s1 == NULL) || (s2 == NULL))
936                                 return FALSE;
937                         s1len = mono_string_length (s1);
938                         s2len = mono_string_length (s2);
939                         if (s1len != s2len)
940                                 return FALSE;
941
942                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
943                                 return FALSE;
944                         break;
945                 }
946                 default:
947                         if (!values)
948                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
949                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
950                         values [count++] = o;
951                         o = mono_field_get_value_object (mono_object_domain (this), field, that);
952                         values [count++] = o;
953                 }
954         }
955
956         if (values) {
957                 int i;
958                 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
959                 for (i = 0; i < count; ++i)
960                         mono_array_setref (*fields, i, values [i]);
961                 return FALSE;
962         } else {
963                 return TRUE;
964         }
965 }
966
967 static MonoReflectionType *
968 ves_icall_System_Object_GetType (MonoObject *obj)
969 {
970         MONO_ARCH_SAVE_REGS;
971
972         if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
973                 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
974         else
975                 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
976 }
977
978 static void
979 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
980 {
981         MONO_ARCH_SAVE_REGS;
982
983         mtype->type = &obj->vtable->klass->byval_arg;
984         g_assert (mtype->type->type);
985 }
986
987 static gint32
988 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
989 {
990         MONO_ARCH_SAVE_REGS;
991         
992         MONO_CHECK_ARG_NULL (obj);
993         
994         return mono_image_create_token (mb->dynamic_image, obj, TRUE);
995 }
996
997 static gint32
998 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
999                                         MonoReflectionMethod *method,
1000                                         MonoArray *opt_param_types)
1001 {
1002         MONO_ARCH_SAVE_REGS;
1003
1004         MONO_CHECK_ARG_NULL (method);
1005         
1006         return mono_image_create_method_token (
1007                 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1008 }
1009
1010 static void
1011 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1012 {
1013         MONO_ARCH_SAVE_REGS;
1014
1015         mono_image_create_pefile (mb, file);
1016 }
1017
1018 static void
1019 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1020 {
1021         MONO_ARCH_SAVE_REGS;
1022
1023         mono_image_build_metadata (mb);
1024 }
1025
1026 static gboolean
1027 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1028 {
1029         MonoMethod **dest = data;
1030
1031         /* skip unmanaged frames */
1032         if (!managed)
1033                 return FALSE;
1034
1035         if (m == *dest) {
1036                 *dest = NULL;
1037                 return FALSE;
1038         }
1039         if (!(*dest)) {
1040                 *dest = m;
1041                 return TRUE;
1042         }
1043         return FALSE;
1044 }
1045
1046 static MonoReflectionType *
1047 type_from_name (const char *str, MonoBoolean ignoreCase)
1048 {
1049         MonoType *type = NULL;
1050         MonoAssembly *assembly = NULL;
1051         MonoTypeNameParse info;
1052         char *temp_str = g_strdup (str);
1053         gboolean type_resolve = FALSE;
1054
1055         MONO_ARCH_SAVE_REGS;
1056
1057         /* mono_reflection_parse_type() mangles the string */
1058         if (!mono_reflection_parse_type (temp_str, &info)) {
1059                 mono_reflection_free_type_info (&info);
1060                 g_free (temp_str);
1061                 return NULL;
1062         }
1063
1064         if (info.assembly.name) {
1065                 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1066         } else {
1067                 MonoMethod *m = mono_method_get_last_managed ();
1068                 MonoMethod *dest = m;
1069
1070                 mono_stack_walk_no_il (get_caller, &dest);
1071                 if (!dest)
1072                         dest = m;
1073
1074                 /*
1075                  * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1076                  *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1077                  *        to crash.  This only seems to happen in some strange remoting
1078                  *        scenarios and I was unable to figure out what's happening there.
1079                  *        Dec 10, 2005 - Martin.
1080                  */
1081
1082                 if (dest)
1083                         assembly = dest->klass->image->assembly;
1084                 else {
1085                         g_warning (G_STRLOC);
1086                 }
1087         }
1088
1089         if (assembly)
1090                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1091         
1092         if (!info.assembly.name && !type) /* try mscorlib */
1093                 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1094
1095         mono_reflection_free_type_info (&info);
1096         g_free (temp_str);
1097
1098         if (!type) 
1099                 return NULL;
1100
1101         return mono_type_get_object (mono_domain_get (), type);
1102 }
1103
1104 #ifdef UNUSED
1105 MonoReflectionType *
1106 mono_type_get (const char *str)
1107 {
1108         char *copy = g_strdup (str);
1109         MonoReflectionType *type = type_from_name (copy, FALSE);
1110
1111         g_free (copy);
1112         return type;
1113 }
1114 #endif
1115
1116 static MonoReflectionType*
1117 ves_icall_type_from_name (MonoString *name,
1118                           MonoBoolean throwOnError,
1119                           MonoBoolean ignoreCase)
1120 {
1121         char *str = mono_string_to_utf8 (name);
1122         MonoReflectionType *type;
1123
1124         type = type_from_name (str, ignoreCase);
1125         g_free (str);
1126         if (type == NULL){
1127                 MonoException *e = NULL;
1128                 
1129                 if (throwOnError)
1130                         e = mono_get_exception_type_load (name, NULL);
1131
1132                 mono_loader_clear_error ();
1133                 if (e != NULL)
1134                         mono_raise_exception (e);
1135         }
1136         
1137         return type;
1138 }
1139
1140
1141 static MonoReflectionType*
1142 ves_icall_type_from_handle (MonoType *handle)
1143 {
1144         MonoDomain *domain = mono_domain_get (); 
1145         MonoClass *klass = mono_class_from_mono_type (handle);
1146
1147         MONO_ARCH_SAVE_REGS;
1148
1149         mono_class_init (klass);
1150         return mono_type_get_object (domain, handle);
1151 }
1152
1153 static MonoBoolean
1154 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1155 {
1156         MONO_ARCH_SAVE_REGS;
1157
1158         if (c && type->type && c->type)
1159                 return mono_metadata_type_equal (type->type, c->type);
1160         else
1161                 return FALSE;
1162 }
1163
1164 /* System.TypeCode */
1165 typedef enum {
1166         TYPECODE_EMPTY,
1167         TYPECODE_OBJECT,
1168         TYPECODE_DBNULL,
1169         TYPECODE_BOOLEAN,
1170         TYPECODE_CHAR,
1171         TYPECODE_SBYTE,
1172         TYPECODE_BYTE,
1173         TYPECODE_INT16,
1174         TYPECODE_UINT16,
1175         TYPECODE_INT32,
1176         TYPECODE_UINT32,
1177         TYPECODE_INT64,
1178         TYPECODE_UINT64,
1179         TYPECODE_SINGLE,
1180         TYPECODE_DOUBLE,
1181         TYPECODE_DECIMAL,
1182         TYPECODE_DATETIME,
1183         TYPECODE_STRING = 18
1184 } TypeCode;
1185
1186 static guint32
1187 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1188 {
1189         int t = type->type->type;
1190
1191         MONO_ARCH_SAVE_REGS;
1192
1193         if (type->type->byref)
1194                 return TYPECODE_OBJECT;
1195
1196 handle_enum:
1197         switch (t) {
1198         case MONO_TYPE_VOID:
1199                 return TYPECODE_OBJECT;
1200         case MONO_TYPE_BOOLEAN:
1201                 return TYPECODE_BOOLEAN;
1202         case MONO_TYPE_U1:
1203                 return TYPECODE_BYTE;
1204         case MONO_TYPE_I1:
1205                 return TYPECODE_SBYTE;
1206         case MONO_TYPE_U2:
1207                 return TYPECODE_UINT16;
1208         case MONO_TYPE_I2:
1209                 return TYPECODE_INT16;
1210         case MONO_TYPE_CHAR:
1211                 return TYPECODE_CHAR;
1212         case MONO_TYPE_PTR:
1213         case MONO_TYPE_U:
1214         case MONO_TYPE_I:
1215                 return TYPECODE_OBJECT;
1216         case MONO_TYPE_U4:
1217                 return TYPECODE_UINT32;
1218         case MONO_TYPE_I4:
1219                 return TYPECODE_INT32;
1220         case MONO_TYPE_U8:
1221                 return TYPECODE_UINT64;
1222         case MONO_TYPE_I8:
1223                 return TYPECODE_INT64;
1224         case MONO_TYPE_R4:
1225                 return TYPECODE_SINGLE;
1226         case MONO_TYPE_R8:
1227                 return TYPECODE_DOUBLE;
1228         case MONO_TYPE_VALUETYPE:
1229                 if (type->type->data.klass->enumtype) {
1230                         t = type->type->data.klass->enum_basetype->type;
1231                         goto handle_enum;
1232                 } else {
1233                         MonoClass *k =  type->type->data.klass;
1234                         if (strcmp (k->name_space, "System") == 0) {
1235                                 if (strcmp (k->name, "Decimal") == 0)
1236                                         return TYPECODE_DECIMAL;
1237                                 else if (strcmp (k->name, "DateTime") == 0)
1238                                         return TYPECODE_DATETIME;
1239                         }
1240                 }
1241                 return TYPECODE_OBJECT;
1242         case MONO_TYPE_STRING:
1243                 return TYPECODE_STRING;
1244         case MONO_TYPE_SZARRAY:
1245         case MONO_TYPE_ARRAY:
1246         case MONO_TYPE_OBJECT:
1247         case MONO_TYPE_VAR:
1248         case MONO_TYPE_MVAR:
1249         case MONO_TYPE_TYPEDBYREF:
1250                 return TYPECODE_OBJECT;
1251         case MONO_TYPE_CLASS:
1252                 {
1253                         MonoClass *k =  type->type->data.klass;
1254                         if (strcmp (k->name_space, "System") == 0) {
1255                                 if (strcmp (k->name, "DBNull") == 0)
1256                                         return TYPECODE_DBNULL;
1257                         }
1258                 }
1259                 return TYPECODE_OBJECT;
1260         case MONO_TYPE_GENERICINST:
1261                 return TYPECODE_OBJECT;
1262         default:
1263                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1264         }
1265         return 0;
1266 }
1267
1268 static guint32
1269 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1270 {
1271         MonoDomain *domain; 
1272         MonoClass *klass;
1273         MonoClass *klassc;
1274
1275         MONO_ARCH_SAVE_REGS;
1276
1277         g_assert (type != NULL);
1278         
1279         domain = ((MonoObject *)type)->vtable->domain;
1280
1281         if (!c) /* FIXME: dont know what do do here */
1282                 return 0;
1283
1284         klass = mono_class_from_mono_type (type->type);
1285         klassc = mono_class_from_mono_type (c->type);
1286
1287         if (type->type->byref)
1288                 return klassc == mono_defaults.object_class;
1289
1290         return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1291 }
1292
1293 static guint32
1294 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1295 {
1296         MonoDomain *domain; 
1297         MonoClass *klass;
1298         MonoClass *klassc;
1299
1300         MONO_ARCH_SAVE_REGS;
1301
1302         g_assert (type != NULL);
1303         
1304         domain = ((MonoObject *)type)->vtable->domain;
1305
1306         klass = mono_class_from_mono_type (type->type);
1307         klassc = mono_class_from_mono_type (c->type);
1308
1309         if (type->type->byref && !c->type->byref)
1310                 return FALSE;
1311
1312         return mono_class_is_assignable_from (klass, klassc);
1313 }
1314
1315 static guint32
1316 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1317 {
1318         MonoClass *klass = mono_class_from_mono_type (type->type);
1319         return mono_object_isinst (obj, klass) != NULL;
1320 }
1321
1322 static guint32
1323 ves_icall_get_attributes (MonoReflectionType *type)
1324 {
1325         MonoClass *klass = mono_class_from_mono_type (type->type);
1326
1327         MONO_ARCH_SAVE_REGS;
1328
1329         return klass->flags;
1330 }
1331
1332 static MonoReflectionMarshal*
1333 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1334 {
1335         MonoClass *klass = field->field->parent;
1336         MonoMarshalType *info;
1337         int i;
1338
1339         if (klass->generic_container ||
1340             (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1341                 return NULL;
1342
1343         info = mono_marshal_load_type_info (klass);
1344
1345         for (i = 0; i < info->num_fields; ++i) {
1346                 if (info->fields [i].field == field->field) {
1347                         if (!info->fields [i].mspec)
1348                                 return NULL;
1349                         else
1350                                 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1351                 }
1352         }
1353
1354         return NULL;
1355 }
1356
1357 static MonoReflectionField*
1358 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1359 {
1360         g_assert (handle);
1361
1362         if (!klass)
1363                 klass = handle->parent;
1364
1365         /* FIXME: check that handle is a field of klass or of a parent: return null
1366          * and throw the exception in managed code.
1367          */
1368         return mono_field_get_object (mono_domain_get (), klass, handle);
1369 }
1370
1371 static MonoReflectionField*
1372 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1373 {
1374         MONO_ARCH_SAVE_REGS;
1375
1376         g_assert (handle);
1377
1378         return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1379 }
1380
1381 static MonoArray*
1382 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1383 {
1384         MonoType *type = field->field->type;
1385
1386         return type_array_from_modifiers (field->field->parent->image, type, optional);
1387 }
1388
1389 static void
1390 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1391 {
1392         MonoDomain *domain = mono_domain_get ();
1393         MonoMethodSignature* sig;
1394         MONO_ARCH_SAVE_REGS;
1395
1396         sig = mono_method_signature (method);
1397         if (!sig) {
1398                 g_assert (mono_loader_get_last_error ());
1399                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1400         }
1401         
1402         info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1403         info->ret = mono_type_get_object (domain, sig->ret);
1404         info->attrs = method->flags;
1405         info->implattrs = method->iflags;
1406         if (sig->call_convention == MONO_CALL_DEFAULT)
1407                 info->callconv = 1;
1408         else {
1409                 if (sig->call_convention == MONO_CALL_VARARG)
1410                         info->callconv = 2;
1411                 else
1412                         info->callconv = 0;
1413         }
1414         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1415 }
1416
1417 static MonoArray*
1418 ves_icall_get_parameter_info (MonoMethod *method)
1419 {
1420         MonoDomain *domain = mono_domain_get (); 
1421
1422         return mono_param_get_objects (domain, method);
1423 }
1424
1425 static MonoReflectionMarshal*
1426 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1427 {
1428         MonoDomain *domain = mono_domain_get (); 
1429         MonoReflectionMarshal* res = NULL;
1430         MonoMarshalSpec **mspecs;
1431         int i;
1432
1433         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1434         mono_method_get_marshal_info (method, mspecs);
1435
1436         if (mspecs [0])
1437                 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1438                 
1439         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1440                 if (mspecs [i])
1441                         mono_metadata_free_marshal_spec (mspecs [i]);
1442         g_free (mspecs);
1443
1444         return res;
1445 }
1446
1447 static gint32
1448 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1449 {
1450         return field->field->offset - sizeof (MonoObject);
1451 }
1452
1453 static MonoReflectionType*
1454 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1455 {
1456         MonoClass *parent;
1457         MONO_ARCH_SAVE_REGS;
1458
1459         parent = declaring? field->field->parent: field->klass;
1460
1461         return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1462 }
1463
1464 static MonoObject *
1465 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1466 {       
1467         MonoObject *o;
1468         MonoClassField *cf = field->field;
1469         MonoClass *klass;
1470         MonoVTable *vtable;
1471         MonoType *t;
1472         MonoDomain *domain = mono_object_domain (field); 
1473         gchar *v;
1474         gboolean is_static = FALSE;
1475         gboolean is_ref = FALSE;
1476
1477         MONO_ARCH_SAVE_REGS;
1478
1479         if (field->klass->image->assembly->ref_only)
1480                 mono_raise_exception (mono_get_exception_invalid_operation (
1481                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1482         
1483         mono_class_init (field->klass);
1484
1485         t = mono_type_get_underlying_type (cf->type);
1486         switch (t->type) {
1487         case MONO_TYPE_STRING:
1488         case MONO_TYPE_OBJECT:
1489         case MONO_TYPE_CLASS:
1490         case MONO_TYPE_ARRAY:
1491         case MONO_TYPE_SZARRAY:
1492                 is_ref = TRUE;
1493                 break;
1494         case MONO_TYPE_U1:
1495         case MONO_TYPE_I1:
1496         case MONO_TYPE_BOOLEAN:
1497         case MONO_TYPE_U2:
1498         case MONO_TYPE_I2:
1499         case MONO_TYPE_CHAR:
1500         case MONO_TYPE_U:
1501         case MONO_TYPE_I:
1502         case MONO_TYPE_U4:
1503         case MONO_TYPE_I4:
1504         case MONO_TYPE_R4:
1505         case MONO_TYPE_U8:
1506         case MONO_TYPE_I8:
1507         case MONO_TYPE_R8:
1508         case MONO_TYPE_VALUETYPE:
1509                 is_ref = t->byref;
1510                 break;
1511         case MONO_TYPE_GENERICINST:
1512                 if (mono_type_generic_inst_is_valuetype (t)) {
1513                         is_ref = t->byref;
1514                 } else {
1515                         is_ref = TRUE;
1516                 }
1517                 break;
1518         default:
1519                 g_error ("type 0x%x not handled in "
1520                          "ves_icall_Monofield_GetValue", t->type);
1521                 return NULL;
1522         }
1523
1524         vtable = NULL;
1525         if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1526                 is_static = TRUE;
1527                 vtable = mono_class_vtable (domain, cf->parent);
1528                 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1529                         mono_runtime_class_init (vtable);
1530         }
1531         
1532         if (is_ref) {
1533                 if (is_static) {
1534                         mono_field_static_get_value (vtable, cf, &o);
1535                 } else {
1536                         mono_field_get_value (obj, cf, &o);
1537                 }
1538                 return o;
1539         }
1540
1541         if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1542                 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1543                 guint8 *buf;
1544
1545                 /* Convert the Nullable structure into a boxed vtype */
1546                 if (is_static)
1547                         buf = (guint8*)vtable->data + cf->offset;
1548                 else
1549                         buf = (guint8*)obj + cf->offset;
1550
1551                 return mono_nullable_box (buf, nklass);
1552         }
1553
1554         /* boxed value type */
1555         klass = mono_class_from_mono_type (cf->type);
1556         o = mono_object_new (domain, klass);
1557         v = ((gchar *) o) + sizeof (MonoObject);
1558         if (is_static) {
1559                 mono_field_static_get_value (vtable, cf, v);
1560         } else {
1561                 mono_field_get_value (obj, cf, v);
1562         }
1563
1564         return o;
1565 }
1566
1567 static void
1568 ves_icall_FieldInfo_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1569 {
1570         MonoClassField *cf = field->field;
1571         gchar *v;
1572
1573         MONO_ARCH_SAVE_REGS;
1574
1575         if (field->klass->image->assembly->ref_only)
1576                 mono_raise_exception (mono_get_exception_invalid_operation (
1577                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1578
1579         v = (gchar *) value;
1580         if (!cf->type->byref) {
1581                 switch (cf->type->type) {
1582                 case MONO_TYPE_U1:
1583                 case MONO_TYPE_I1:
1584                 case MONO_TYPE_BOOLEAN:
1585                 case MONO_TYPE_U2:
1586                 case MONO_TYPE_I2:
1587                 case MONO_TYPE_CHAR:
1588                 case MONO_TYPE_U:
1589                 case MONO_TYPE_I:
1590                 case MONO_TYPE_U4:
1591                 case MONO_TYPE_I4:
1592                 case MONO_TYPE_R4:
1593                 case MONO_TYPE_U8:
1594                 case MONO_TYPE_I8:
1595                 case MONO_TYPE_R8:
1596                 case MONO_TYPE_VALUETYPE:
1597                         if (v != NULL)
1598                                 v += sizeof (MonoObject);
1599                         break;
1600                 case MONO_TYPE_STRING:
1601                 case MONO_TYPE_OBJECT:
1602                 case MONO_TYPE_CLASS:
1603                 case MONO_TYPE_ARRAY:
1604                 case MONO_TYPE_SZARRAY:
1605                         /* Do nothing */
1606                         break;
1607                 case MONO_TYPE_GENERICINST: {
1608                         MonoGenericClass *gclass = cf->type->data.generic_class;
1609                         g_assert (!gclass->context.class_inst->is_open);
1610
1611                         if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1612                                 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1613                                 MonoObject *nullable;
1614
1615                                 /* 
1616                                  * Convert the boxed vtype into a Nullable structure.
1617                                  * This is complicated by the fact that Nullables have
1618                                  * a variable structure.
1619                                  */
1620                                 nullable = mono_object_new (mono_domain_get (), nklass);
1621
1622                                 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1623
1624                                 v = mono_object_unbox (nullable);
1625                         }
1626                         else 
1627                                 if (gclass->container_class->valuetype && (v != NULL))
1628                                         v += sizeof (MonoObject);
1629                         break;
1630                 }
1631                 default:
1632                         g_error ("type 0x%x not handled in "
1633                                  "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1634                         return;
1635                 }
1636         }
1637
1638         if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1639                 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1640                 if (!vtable->initialized)
1641                         mono_runtime_class_init (vtable);
1642                 mono_field_static_set_value (vtable, cf, v);
1643         } else {
1644                 mono_field_set_value (obj, cf, v);
1645         }
1646 }
1647
1648 static MonoReflectionType*
1649 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1650 {
1651         MonoMethod *method = rmethod->method.method;
1652
1653         return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1654 }
1655
1656 /* From MonoProperty.cs */
1657 typedef enum {
1658         PInfo_Attributes = 1,
1659         PInfo_GetMethod  = 1 << 1,
1660         PInfo_SetMethod  = 1 << 2,
1661         PInfo_ReflectedType = 1 << 3,
1662         PInfo_DeclaringType = 1 << 4,
1663         PInfo_Name = 1 << 5
1664 } PInfo;
1665
1666 static void
1667 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1668 {
1669         MonoDomain *domain = mono_object_domain (property); 
1670
1671         MONO_ARCH_SAVE_REGS;
1672
1673         if ((req_info & PInfo_ReflectedType) != 0)
1674                 info->parent = mono_type_get_object (domain, &property->klass->byval_arg);
1675         else if ((req_info & PInfo_DeclaringType) != 0)
1676                 info->parent = mono_type_get_object (domain, &property->property->parent->byval_arg);
1677
1678         if ((req_info & PInfo_Name) != 0)
1679                 info->name = mono_string_new (domain, property->property->name);
1680
1681         if ((req_info & PInfo_Attributes) != 0)
1682                 info->attrs = property->property->attrs;
1683
1684         if ((req_info & PInfo_GetMethod) != 0)
1685                 info->get = property->property->get ?
1686                             mono_method_get_object (domain, property->property->get, NULL): NULL;
1687         
1688         if ((req_info & PInfo_SetMethod) != 0)
1689                 info->set = property->property->set ?
1690                             mono_method_get_object (domain, property->property->set, NULL): NULL;
1691         /* 
1692          * There may be other methods defined for properties, though, it seems they are not exposed 
1693          * in the reflection API 
1694          */
1695 }
1696
1697 static void
1698 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1699 {
1700         MonoDomain *domain = mono_object_domain (event); 
1701
1702         MONO_ARCH_SAVE_REGS;
1703
1704         info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1705         info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1706
1707         info->name = mono_string_new (domain, event->event->name);
1708         info->attrs = event->event->attrs;
1709         info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1710         info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1711         info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1712
1713         if (event->event->other) {
1714                 int i, n = 0;
1715                 while (event->event->other [n])
1716                         n++;
1717                 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1718
1719                 for (i = 0; i < n; i++)
1720                         mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1721         }               
1722 }
1723
1724 static MonoArray*
1725 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1726 {
1727         MonoDomain *domain = mono_object_domain (type); 
1728         MonoArray *intf;
1729         GPtrArray *ifaces = NULL;
1730         int i;
1731         MonoClass *class = mono_class_from_mono_type (type->type);
1732         MonoClass *parent;
1733         MonoBitSet *slots;
1734         MonoGenericContext *context = NULL;
1735
1736         MONO_ARCH_SAVE_REGS;
1737
1738         if (class->generic_class && class->generic_class->context.class_inst->is_open) {
1739                 context = mono_class_get_context (class);
1740                 class = class->generic_class->container_class;
1741         }
1742
1743         mono_class_setup_vtable (class);
1744
1745         slots = mono_bitset_new (class->max_interface_id + 1, 0);
1746
1747         for (parent = class; parent; parent = parent->parent) {
1748                 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
1749                 if (tmp_ifaces) {
1750                         for (i = 0; i < tmp_ifaces->len; ++i) {
1751                                 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
1752
1753                                 if (mono_bitset_test (slots, ic->interface_id))
1754                                         continue;
1755
1756                                 mono_bitset_set (slots, ic->interface_id);
1757                                 if (ifaces == NULL)
1758                                         ifaces = g_ptr_array_new ();
1759                                 g_ptr_array_add (ifaces, ic);
1760                         }
1761                         g_ptr_array_free (tmp_ifaces, TRUE);
1762                 }
1763         }
1764         mono_bitset_free (slots);
1765
1766         if (!ifaces)
1767                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
1768                 
1769         intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
1770         for (i = 0; i < ifaces->len; ++i) {
1771                 MonoClass *ic = g_ptr_array_index (ifaces, i);
1772                 MonoType *ret = &ic->byval_arg;
1773                 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
1774                         ret = mono_class_inflate_generic_type (ret, context);
1775                 
1776                 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
1777         }
1778         g_ptr_array_free (ifaces, TRUE);
1779
1780         return intf;
1781 }
1782
1783 static void
1784 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
1785 {
1786         MonoClass *class = mono_class_from_mono_type (type->type);
1787         MonoClass *iclass = mono_class_from_mono_type (iface->type);
1788         MonoReflectionMethod *member;
1789         MonoMethod* method;
1790         gpointer iter;
1791         int i = 0, len, ioffset;
1792         MonoDomain *domain;
1793
1794         MONO_ARCH_SAVE_REGS;
1795
1796         mono_class_setup_vtable (class);
1797
1798         /* type doesn't implement iface: the exception is thrown in managed code */
1799         if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
1800                         return;
1801
1802         len = mono_class_num_methods (iclass);
1803         ioffset = mono_class_interface_offset (class, iclass);
1804         domain = mono_object_domain (type);
1805         *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
1806         *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
1807         iter = NULL;
1808         iter = NULL;
1809         while ((method = mono_class_get_methods (iclass, &iter))) {
1810                 member = mono_method_get_object (domain, method, iclass);
1811                 mono_array_setref (*methods, i, member);
1812                 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
1813                 mono_array_setref (*targets, i, member);
1814                 
1815                 i ++;
1816         }
1817 }
1818
1819 static void
1820 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
1821 {
1822         MonoClass *klass = mono_class_from_mono_type (type->type);
1823
1824         g_assert (!klass->image->dynamic);
1825
1826         mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
1827 }
1828
1829 static MonoReflectionType*
1830 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
1831 {
1832         MonoClass *class = mono_class_from_mono_type (type->type);
1833
1834         MONO_ARCH_SAVE_REGS;
1835
1836         // GelElementType should only return a type for:
1837         // Array Pointer PassedByRef
1838         if (type->type->byref)
1839                 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
1840         if (class->enumtype && class->enum_basetype) /* types that are modifierd typebuilkders may not have enum_basetype set */
1841                 return mono_type_get_object (mono_object_domain (type), class->enum_basetype);
1842         else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
1843                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1844         else if (class->element_class && type->type->type == MONO_TYPE_PTR)
1845                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1846         else
1847                 return NULL;
1848 }
1849
1850 static MonoReflectionType*
1851 ves_icall_get_type_parent (MonoReflectionType *type)
1852 {
1853         MonoClass *class = mono_class_from_mono_type (type->type);
1854
1855         MONO_ARCH_SAVE_REGS;
1856
1857         return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
1858 }
1859
1860 static MonoBoolean
1861 ves_icall_type_ispointer (MonoReflectionType *type)
1862 {
1863         MONO_ARCH_SAVE_REGS;
1864
1865         return type->type->type == MONO_TYPE_PTR;
1866 }
1867
1868 static MonoBoolean
1869 ves_icall_type_isprimitive (MonoReflectionType *type)
1870 {
1871         MONO_ARCH_SAVE_REGS;
1872
1873         return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
1874 }
1875
1876 static MonoBoolean
1877 ves_icall_type_isbyref (MonoReflectionType *type)
1878 {
1879         MONO_ARCH_SAVE_REGS;
1880
1881         return type->type->byref;
1882 }
1883
1884 static MonoBoolean
1885 ves_icall_type_iscomobject (MonoReflectionType *type)
1886 {
1887         MonoClass *klass = mono_class_from_mono_type (type->type);
1888         MONO_ARCH_SAVE_REGS;
1889
1890         return (klass && klass->is_com_object);
1891 }
1892
1893 static MonoReflectionModule*
1894 ves_icall_MonoType_get_Module (MonoReflectionType *type)
1895 {
1896         MonoClass *class = mono_class_from_mono_type (type->type);
1897
1898         MONO_ARCH_SAVE_REGS;
1899
1900         return mono_module_get_object (mono_object_domain (type), class->image);
1901 }
1902
1903 static MonoReflectionAssembly*
1904 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
1905 {
1906         MonoDomain *domain = mono_domain_get (); 
1907         MonoClass *class = mono_class_from_mono_type (type->type);
1908
1909         MONO_ARCH_SAVE_REGS;
1910
1911         return mono_assembly_get_object (domain, class->image->assembly);
1912 }
1913
1914 static MonoReflectionType*
1915 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
1916 {
1917         MonoDomain *domain = mono_domain_get ();
1918         MonoClass *class;
1919
1920         MONO_ARCH_SAVE_REGS;
1921
1922         if (type->type->byref)
1923                 return NULL;
1924         if (type->type->type == MONO_TYPE_VAR)
1925                 class = type->type->data.generic_param->owner->owner.klass;
1926         else if (type->type->type == MONO_TYPE_MVAR)
1927                 class = type->type->data.generic_param->owner->owner.method->klass;
1928         else
1929                 class = mono_class_from_mono_type (type->type)->nested_in;
1930
1931         return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
1932 }
1933
1934 static MonoReflectionType*
1935 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
1936 {
1937         MonoDomain *domain = mono_domain_get (); 
1938         MonoClass *class = mono_class_from_mono_type (type->type);
1939
1940         MONO_ARCH_SAVE_REGS;
1941
1942         if (class->enumtype && class->enum_basetype) /* types that are modified typebuilders may not have enum_basetype set */
1943                 return mono_type_get_object (domain, class->enum_basetype);
1944         else if (class->element_class)
1945                 return mono_type_get_object (domain, &class->element_class->byval_arg);
1946         else
1947                 return NULL;
1948 }
1949
1950 static MonoString*
1951 ves_icall_MonoType_get_Name (MonoReflectionType *type)
1952 {
1953         MonoDomain *domain = mono_domain_get (); 
1954         MonoClass *class = mono_class_from_mono_type (type->type);
1955
1956         MONO_ARCH_SAVE_REGS;
1957
1958         if (type->type->byref) {
1959                 char *n = g_strdup_printf ("%s&", class->name);
1960                 MonoString *res = mono_string_new (domain, n);
1961
1962                 g_free (n);
1963
1964                 return res;
1965         } else {
1966                 return mono_string_new (domain, class->name);
1967         }
1968 }
1969
1970 static MonoString*
1971 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
1972 {
1973         MonoDomain *domain = mono_domain_get (); 
1974         MonoClass *class = mono_class_from_mono_type (type->type);
1975
1976         MONO_ARCH_SAVE_REGS;
1977
1978         while (class->nested_in)
1979                 class = class->nested_in;
1980
1981         if (class->name_space [0] == '\0')
1982                 return NULL;
1983         else
1984                 return mono_string_new (domain, class->name_space);
1985 }
1986
1987 static gint32
1988 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
1989 {
1990         MonoClass *class = mono_class_from_mono_type (type->type);
1991
1992         MONO_ARCH_SAVE_REGS;
1993
1994         return class->rank;
1995 }
1996
1997 static MonoArray*
1998 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
1999 {
2000         MonoArray *res;
2001         MonoClass *klass, *pklass;
2002         int i;
2003         MONO_ARCH_SAVE_REGS;
2004
2005         klass = mono_class_from_mono_type (type->type);
2006
2007         if (klass->generic_container) {
2008                 MonoGenericContainer *container = klass->generic_container;
2009                 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, container->type_argc);
2010                 for (i = 0; i < container->type_argc; ++i) {
2011                         pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
2012                         mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
2013                 }
2014         } else if (klass->generic_class) {
2015                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2016                 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, inst->type_argc);
2017                 for (i = 0; i < inst->type_argc; ++i)
2018                         mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
2019         } else {
2020                 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, 0);
2021         }
2022         return res;
2023 }
2024
2025 static gboolean
2026 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2027 {
2028         MonoClass *klass;
2029         MONO_ARCH_SAVE_REGS;
2030
2031         if (type->type->byref)
2032                 return FALSE;
2033
2034         klass = mono_class_from_mono_type (type->type);
2035
2036         return klass->generic_container != NULL;
2037 }
2038
2039 static MonoReflectionType*
2040 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2041 {
2042         MonoClass *klass;
2043         MONO_ARCH_SAVE_REGS;
2044
2045         if (type->type->byref)
2046                 return NULL;
2047
2048         klass = mono_class_from_mono_type (type->type);
2049         if (klass->generic_container) {
2050                 return type; /* check this one */
2051         }
2052         if (klass->generic_class) {
2053                 MonoClass *generic_class = klass->generic_class->container_class;
2054
2055                 if (generic_class->wastypebuilder && generic_class->reflection_info)
2056                         return generic_class->reflection_info;
2057                 else
2058                         return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2059         }
2060         return NULL;
2061 }
2062
2063 static MonoReflectionType*
2064 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2065 {
2066         MonoType *geninst, **types;
2067         int i, count;
2068
2069         MONO_ARCH_SAVE_REGS;
2070
2071         count = mono_array_length (type_array);
2072         types = g_new0 (MonoType *, count);
2073
2074         for (i = 0; i < count; i++) {
2075                 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2076                 types [i] = t->type;
2077         }
2078
2079         geninst = mono_reflection_bind_generic_parameters (type, count, types);
2080         g_free (types);
2081         if (!geninst)
2082                 return NULL;
2083
2084         return mono_type_get_object (mono_object_domain (type), geninst);
2085 }
2086
2087 static gboolean
2088 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2089 {
2090         MonoClass *klass;
2091         MONO_ARCH_SAVE_REGS;
2092
2093         if (type->type->byref)
2094                 return FALSE;
2095
2096         klass = mono_class_from_mono_type (type->type);
2097         return klass->generic_class != NULL;
2098 }
2099
2100 static gboolean
2101 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2102 {
2103         MonoClass *klass;
2104         MONO_ARCH_SAVE_REGS;
2105
2106         if (type->type->byref)
2107                 return FALSE;
2108
2109         klass = mono_class_from_mono_type (type->type);
2110         return klass->generic_class != NULL || klass->generic_container != NULL;
2111 }
2112
2113 static gint32
2114 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2115 {
2116         MONO_ARCH_SAVE_REGS;
2117
2118         if (is_generic_parameter (type->type))
2119                 return type->type->data.generic_param->num;
2120         return -1;
2121 }
2122
2123 static GenericParameterAttributes
2124 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2125 {
2126         MONO_ARCH_SAVE_REGS;
2127         g_assert (is_generic_parameter (type->type));
2128         return type->type->data.generic_param->flags;
2129 }
2130
2131 static MonoArray *
2132 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2133 {
2134         MonoGenericParam *param;
2135         MonoDomain *domain;
2136         MonoClass **ptr;
2137         MonoArray *res;
2138         int i, count;
2139
2140         MONO_ARCH_SAVE_REGS;
2141
2142         domain = mono_object_domain (type);
2143         param = type->type->data.generic_param;
2144         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2145                 ;
2146
2147         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2148         for (i = 0; i < count; i++)
2149                 mono_array_setref (res, i, mono_type_get_object (domain, &param->constraints [i]->byval_arg));
2150
2151
2152         return res;
2153 }
2154
2155 static MonoBoolean
2156 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2157 {
2158         MONO_ARCH_SAVE_REGS;
2159         return is_generic_parameter (type->type);
2160 }
2161
2162 static MonoBoolean
2163 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2164 {
2165         MONO_ARCH_SAVE_REGS;
2166         return is_generic_parameter (tb->type.type);
2167 }
2168
2169 static void
2170 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2171                                                                            MonoReflectionType *t)
2172 {
2173         enumtype->type = t->type;
2174 }
2175
2176 static MonoReflectionType*
2177 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2178 {
2179         MonoDynamicGenericClass *gclass;
2180         MonoReflectionType *parent = NULL;
2181         MonoDomain *domain;
2182         MonoType *inflated;
2183         MonoClass *klass;
2184
2185         MONO_ARCH_SAVE_REGS;
2186
2187         g_assert (type->type.type->data.generic_class->is_dynamic);
2188         gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2189
2190         domain = mono_object_domain (type);
2191         klass = mono_class_from_mono_type (type->generic_type->type);
2192
2193         if (!klass->generic_class && !klass->generic_container)
2194                 return NULL;
2195
2196         if (!strcmp (type->generic_type->object.vtable->klass->name, "TypeBuilder")) {
2197                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *) type->generic_type;
2198                 parent = tb->parent;
2199         } else if (klass->wastypebuilder) {
2200                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *) type->generic_type;
2201                 parent = tb->parent;
2202         } else {
2203                 MonoClass *pklass = klass->parent;
2204                 if (pklass)
2205                         parent = mono_type_get_object (domain, &pklass->byval_arg);
2206         }
2207
2208         if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2209                 return NULL;
2210
2211         inflated = mono_class_inflate_generic_type (
2212                 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2213
2214         return mono_type_get_object (domain, inflated);
2215 }
2216
2217 static MonoArray*
2218 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2219 {
2220         static MonoClass *System_Reflection_MonoGenericClass;
2221         MonoGenericClass *gclass;
2222         MonoReflectionTypeBuilder *tb = NULL;
2223         MonoClass *klass = NULL;
2224         MonoDomain *domain;
2225         MonoArray *res;
2226         int icount, i;
2227
2228         MONO_ARCH_SAVE_REGS;
2229
2230         if (!System_Reflection_MonoGenericClass) {
2231                 System_Reflection_MonoGenericClass = mono_class_from_name (
2232                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2233                 g_assert (System_Reflection_MonoGenericClass);
2234         }
2235
2236         domain = mono_object_domain (type);
2237
2238         gclass = type->type.type->data.generic_class;
2239         g_assert (gclass->is_dynamic);
2240
2241         if (!strcmp (type->generic_type->object.vtable->klass->name, "TypeBuilder")) {
2242                 tb = (MonoReflectionTypeBuilder *) type->generic_type;
2243                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2244         } else {
2245                 klass = gclass->container_class;
2246                 mono_class_init (klass);
2247                 icount = klass->interface_count;
2248         }
2249
2250         res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2251
2252         for (i = 0; i < icount; i++) {
2253                 MonoReflectionType *iface;
2254                 MonoType *it;
2255
2256                 if (tb) {
2257                         iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2258                         it = iface->type;
2259                 } else
2260                         it = &klass->interfaces [i]->byval_arg;
2261
2262                 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2263
2264                 iface = mono_type_get_object (domain, it);
2265                 mono_array_setref (res, i, iface);
2266         }
2267
2268         return res;
2269 }
2270
2271 static MonoReflectionMethod*
2272 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type, 
2273                                                            MonoReflectionMethod* generic)
2274 {
2275         MonoGenericClass *gclass;
2276         MonoDynamicGenericClass *dgclass;
2277         MonoDomain *domain;
2278         int i;
2279
2280         MONO_ARCH_SAVE_REGS;
2281
2282         gclass = type->type.type->data.generic_class;
2283         g_assert (gclass->is_dynamic);
2284
2285         dgclass = (MonoDynamicGenericClass *) gclass;
2286
2287         domain = mono_object_domain (type);
2288
2289         for (i = 0; i < dgclass->count_methods; i++)
2290                 if (generic->method->token == dgclass->methods [i]->token)
2291                         return mono_method_get_object (domain, dgclass->methods [i], NULL);
2292
2293         return NULL;
2294 }
2295
2296 static MonoReflectionMethod*
2297 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type, 
2298                                                                 MonoReflectionMethod* generic)
2299 {
2300         MonoGenericClass *gclass;
2301         MonoDynamicGenericClass *dgclass;
2302         MonoDomain *domain;
2303         int i;
2304
2305         MONO_ARCH_SAVE_REGS;
2306
2307         gclass = type->type.type->data.generic_class;
2308         g_assert (gclass->is_dynamic);
2309
2310         dgclass = (MonoDynamicGenericClass *) gclass;
2311
2312         domain = mono_object_domain (type);
2313
2314         for (i = 0; i < dgclass->count_ctors; i++)
2315                 if (generic->method->token == dgclass->ctors [i]->token)
2316                         return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2317
2318         return NULL;
2319 }
2320
2321
2322 static MonoReflectionField*
2323 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type, 
2324                                                           MonoString* generic_name)
2325 {
2326         MonoGenericClass *gclass;
2327         MonoDynamicGenericClass *dgclass;
2328         MonoDomain *domain;
2329         MonoClass *refclass;
2330         char *utf8_name = mono_string_to_utf8 (generic_name);
2331         int i;
2332
2333         MONO_ARCH_SAVE_REGS;
2334
2335         gclass = type->type.type->data.generic_class;
2336         g_assert (gclass->is_dynamic);
2337
2338         dgclass = (MonoDynamicGenericClass *) gclass;
2339
2340         refclass = mono_class_from_mono_type (type->type.type);
2341
2342         domain = mono_object_domain (type);
2343
2344         for (i = 0; i < dgclass->count_fields; i++)
2345                 if (strcmp (utf8_name, dgclass->fields [i].name) == 0) {
2346                         g_free (utf8_name);
2347                         return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2348                 }
2349         
2350         g_free (utf8_name);
2351
2352         return NULL;
2353 }
2354
2355
2356 static MonoReflectionMethod*
2357 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2358                                                    MonoReflectionMethod* generic)
2359 {
2360         MonoDomain *domain; 
2361         MonoClass *klass;
2362         MonoMethod *method;
2363         gpointer iter;
2364                 
2365         MONO_ARCH_SAVE_REGS;
2366
2367         domain = ((MonoObject *)type)->vtable->domain;
2368
2369         klass = mono_class_from_mono_type (type->type);
2370
2371         iter = NULL;
2372         while ((method = mono_class_get_methods (klass, &iter))) {
2373                 if (method->token == generic->method->token)
2374                         return mono_method_get_object (domain, method, klass);
2375         }
2376
2377         return NULL;
2378 }
2379
2380 static MonoArray*
2381 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2382                                        MonoReflectionType *reflected_type)
2383 {
2384         MonoGenericClass *gclass;
2385         MonoDynamicGenericClass *dgclass;
2386         MonoDomain *domain;
2387         MonoClass *refclass;
2388         MonoArray *res;
2389         int i;
2390
2391         MONO_ARCH_SAVE_REGS;
2392
2393         gclass = type->type.type->data.generic_class;
2394         g_assert (gclass->is_dynamic);
2395         dgclass = (MonoDynamicGenericClass *) gclass;
2396
2397         refclass = mono_class_from_mono_type (reflected_type->type);
2398
2399         domain = mono_object_domain (type);
2400         res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2401
2402         for (i = 0; i < dgclass->count_methods; i++)
2403                 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2404
2405         return res;
2406 }
2407
2408 static MonoArray*
2409 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2410                                             MonoReflectionType *reflected_type)
2411 {
2412         static MonoClass *System_Reflection_ConstructorInfo;
2413         MonoGenericClass *gclass;
2414         MonoDynamicGenericClass *dgclass;
2415         MonoDomain *domain;
2416         MonoClass *refclass;
2417         MonoArray *res;
2418         int i;
2419
2420         MONO_ARCH_SAVE_REGS;
2421
2422         if (!System_Reflection_ConstructorInfo)
2423                 System_Reflection_ConstructorInfo = mono_class_from_name (
2424                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2425
2426         gclass = type->type.type->data.generic_class;
2427         g_assert (gclass->is_dynamic);
2428         dgclass = (MonoDynamicGenericClass *) gclass;
2429
2430         refclass = mono_class_from_mono_type (reflected_type->type);
2431
2432         domain = mono_object_domain (type);
2433         res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2434
2435         for (i = 0; i < dgclass->count_ctors; i++)
2436                 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2437
2438         return res;
2439 }
2440
2441 static MonoArray*
2442 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2443                                       MonoReflectionType *reflected_type)
2444 {
2445         MonoGenericClass *gclass;
2446         MonoDynamicGenericClass *dgclass;
2447         MonoDomain *domain;
2448         MonoClass *refclass;
2449         MonoArray *res;
2450         int i;
2451
2452         MONO_ARCH_SAVE_REGS;
2453
2454         gclass = type->type.type->data.generic_class;
2455         g_assert (gclass->is_dynamic);
2456         dgclass = (MonoDynamicGenericClass *) gclass;
2457
2458         refclass = mono_class_from_mono_type (reflected_type->type);
2459
2460         domain = mono_object_domain (type);
2461         res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2462
2463         for (i = 0; i < dgclass->count_fields; i++)
2464                 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2465
2466         return res;
2467 }
2468
2469 static MonoArray*
2470 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2471                                           MonoReflectionType *reflected_type)
2472 {
2473         static MonoClass *System_Reflection_PropertyInfo;
2474         MonoGenericClass *gclass;
2475         MonoDynamicGenericClass *dgclass;
2476         MonoDomain *domain;
2477         MonoClass *refclass;
2478         MonoArray *res;
2479         int i;
2480
2481         MONO_ARCH_SAVE_REGS;
2482
2483         if (!System_Reflection_PropertyInfo)
2484                 System_Reflection_PropertyInfo = mono_class_from_name (
2485                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2486
2487         gclass = type->type.type->data.generic_class;
2488         g_assert (gclass->is_dynamic);
2489         dgclass = (MonoDynamicGenericClass *) gclass;
2490
2491         refclass = mono_class_from_mono_type (reflected_type->type);
2492
2493         domain = mono_object_domain (type);
2494         res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2495
2496         for (i = 0; i < dgclass->count_properties; i++)
2497                 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2498
2499         return res;
2500 }
2501
2502 static MonoArray*
2503 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2504                                       MonoReflectionType *reflected_type)
2505 {
2506         static MonoClass *System_Reflection_EventInfo;
2507         MonoGenericClass *gclass;
2508         MonoDynamicGenericClass *dgclass;
2509         MonoDomain *domain;
2510         MonoClass *refclass;
2511         MonoArray *res;
2512         int i;
2513
2514         MONO_ARCH_SAVE_REGS;
2515
2516         if (!System_Reflection_EventInfo)
2517                 System_Reflection_EventInfo = mono_class_from_name (
2518                         mono_defaults.corlib, "System.Reflection", "EventInfo");
2519
2520         gclass = type->type.type->data.generic_class;
2521         g_assert (gclass->is_dynamic);
2522         dgclass = (MonoDynamicGenericClass *) gclass;
2523
2524         refclass = mono_class_from_mono_type (reflected_type->type);
2525
2526         domain = mono_object_domain (type);
2527         res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2528
2529         for (i = 0; i < dgclass->count_events; i++)
2530                 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2531
2532         return res;
2533 }
2534
2535 static MonoReflectionMethod *
2536 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2537 {
2538         MonoMethod *method;
2539         MonoClass *klass;
2540
2541         MONO_ARCH_SAVE_REGS;
2542
2543         if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2544                 return NULL;
2545
2546         method = type->type->data.generic_param->owner->owner.method;
2547         g_assert (method);
2548         klass = mono_class_from_mono_type (type->type);
2549         return mono_method_get_object (mono_object_domain (type), method, klass);
2550 }
2551
2552 static MonoReflectionDllImportAttribute*
2553 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2554 {
2555         static MonoClass *DllImportAttributeClass = NULL;
2556         MonoDomain *domain = mono_domain_get ();
2557         MonoReflectionDllImportAttribute *attr;
2558         MonoImage *image = method->klass->image;
2559         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2560         MonoTableInfo *tables = image->tables;
2561         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2562         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2563         guint32 im_cols [MONO_IMPLMAP_SIZE];
2564         guint32 scope_token;
2565         const char *import = NULL;
2566         const char *scope = NULL;
2567         guint32 flags;
2568
2569         if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2570                 return NULL;
2571
2572         if (!DllImportAttributeClass) {
2573                 DllImportAttributeClass = 
2574                         mono_class_from_name (mono_defaults.corlib,
2575                                                                   "System.Runtime.InteropServices", "DllImportAttribute");
2576                 g_assert (DllImportAttributeClass);
2577         }
2578                                                                                                                 
2579         if (method->klass->image->dynamic) {
2580                 MonoReflectionMethodAux *method_aux = 
2581                         g_hash_table_lookup (
2582                                                                           ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2583                 if (method_aux) {
2584                         import = method_aux->dllentry;
2585                         scope = method_aux->dll;
2586                 }
2587         }
2588         else {
2589                 if (piinfo->implmap_idx) {
2590                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2591                         
2592                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2593                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2594                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2595                         scope = mono_metadata_string_heap (image, scope_token);
2596                 }
2597         }
2598         flags = piinfo->piflags;
2599         
2600         attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2601
2602         MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2603         MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2604         attr->call_conv = (flags & 0x700) >> 8;
2605         attr->charset = ((flags & 0x6) >> 1) + 1;
2606         if (attr->charset == 1)
2607                 attr->charset = 2;
2608         attr->exact_spelling = (flags & 0x1) != 0;
2609         attr->set_last_error = (flags & 0x40) != 0;
2610         attr->best_fit_mapping = (flags & 0x30) == 0x10;
2611         attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2612         attr->preserve_sig = FALSE;
2613
2614         return attr;
2615 }
2616
2617 static MonoReflectionMethod *
2618 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2619 {
2620         MonoMethodInflated *imethod;
2621
2622         MONO_ARCH_SAVE_REGS;
2623
2624         if (method->method->generic_container)
2625                 return method;
2626
2627         if (!method->method->is_inflated)
2628                 return NULL;
2629
2630         imethod = (MonoMethodInflated *) method->method;
2631
2632         if (imethod->reflection_info)
2633                 return imethod->reflection_info;
2634         else
2635                 return mono_method_get_object (
2636                         mono_object_domain (method), imethod->declaring, NULL);
2637 }
2638
2639 static gboolean
2640 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2641 {
2642         MONO_ARCH_SAVE_REGS;
2643
2644         return mono_method_signature (method->method)->generic_param_count != 0;
2645 }
2646
2647 static gboolean
2648 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2649 {
2650         MONO_ARCH_SAVE_REGS;
2651
2652         return method->method->generic_container != NULL;
2653 }
2654
2655 static MonoArray*
2656 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2657 {
2658         MonoArray *res;
2659         MonoDomain *domain;
2660         int count, i;
2661         MONO_ARCH_SAVE_REGS;
2662
2663         domain = mono_object_domain (method);
2664
2665         if (method->method->is_inflated) {
2666                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2667
2668                 if (inst) {
2669                         count = inst->type_argc;
2670                         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2671
2672                         for (i = 0; i < count; i++)
2673                                 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2674
2675                         return res;
2676                 }
2677         }
2678
2679         count = mono_method_signature (method->method)->generic_param_count;
2680         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2681
2682         for (i = 0; i < count; i++) {
2683                 MonoGenericParam *param = &method->method->generic_container->type_params [i];
2684                 MonoClass *pklass = mono_class_from_generic_parameter (
2685                         param, method->method->klass->image, TRUE);
2686                 mono_array_setref (res, i,
2687                                 mono_type_get_object (domain, &pklass->byval_arg));
2688         }
2689
2690         return res;
2691 }
2692
2693 static void
2694 ensure_reflection_security (void)
2695 {
2696         MonoMethod *m = mono_method_get_last_managed ();
2697
2698         while (m) {
2699                 /*
2700                 g_print ("method %s.%s.%s in image %s\n",
2701                         m->klass->name_space, m->klass->name, m->name, m->klass->image->name);
2702                 */
2703
2704                 /* We stop at the first method which is not in
2705                    System.Reflection or which is not in a platform
2706                    image. */
2707                 if (strcmp (m->klass->name_space, "System.Reflection") != 0 ||
2708                                 !mono_security_core_clr_is_platform_image (m->klass->image)) {
2709                         /* If the method is transparent we throw an exception. */
2710                         if (mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_TRANSPARENT ) {
2711                                 MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Reflection called from transparent code");
2712
2713                                 mono_raise_exception (ex);
2714                         }
2715                         return;
2716                 }
2717
2718                 mono_stack_walk_no_il (get_caller, &m);
2719         }
2720 }
2721
2722 static MonoObject *
2723 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params) 
2724 {
2725         /* 
2726          * Invoke from reflection is supposed to always be a virtual call (the API
2727          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2728          * greater flexibility.
2729          */
2730         MonoMethod *m = method->method;
2731         int pcount;
2732         void *obj = this;
2733
2734         MONO_ARCH_SAVE_REGS;
2735
2736         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
2737                         mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
2738                 ensure_reflection_security ();
2739
2740         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2741                 if (this) {
2742                         if (!mono_object_isinst (this, m->klass))
2743                                 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2744                         m = mono_object_get_virtual_method (this, m);
2745                         /* must pass the pointer to the value for valuetype methods */
2746                         if (m->klass->valuetype)
2747                                 obj = mono_object_unbox (this);
2748                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type)
2749                         mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2750         }
2751
2752         pcount = params? mono_array_length (params): 0;
2753         if (pcount != mono_method_signature (m)->param_count)
2754                 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2755
2756         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this)
2757                 mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Cannot invoke constructor of an abstract class."));
2758
2759         if (m->klass->image->assembly->ref_only)
2760                 mono_raise_exception (mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2761         
2762         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2763                 int i;
2764                 guint32 *lengths;
2765                 guint32 *lower_bounds;
2766                 pcount = mono_array_length (params);
2767                 lengths = alloca (sizeof (guint32) * pcount);
2768                 for (i = 0; i < pcount; ++i)
2769                         lengths [i] = *(gint32*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2770
2771                 if (m->klass->rank == pcount) {
2772                         /* Only lengths provided. */
2773                         lower_bounds = NULL;
2774                 } else {
2775                         g_assert (pcount == (m->klass->rank * 2));
2776                         /* lower bounds are first. */
2777                         lower_bounds = lengths;
2778                         lengths += m->klass->rank;
2779                 }
2780
2781                 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2782         }
2783         return mono_runtime_invoke_array (m, obj, params, NULL);
2784 }
2785
2786 static MonoObject *
2787 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
2788 {
2789         MonoDomain *domain = mono_object_domain (method); 
2790         MonoMethod *m = method->method;
2791         MonoMethodSignature *sig = mono_method_signature (m);
2792         MonoArray *out_args;
2793         MonoObject *result;
2794         int i, j, outarg_count = 0;
2795
2796         MONO_ARCH_SAVE_REGS;
2797
2798         if (m->klass == mono_defaults.object_class) {
2799
2800                 if (!strcmp (m->name, "FieldGetter")) {
2801                         MonoClass *k = this->vtable->klass;
2802                         MonoString *name;
2803                         char *str;
2804                         
2805                         /* If this is a proxy, then it must be a CBO */
2806                         if (k == mono_defaults.transparent_proxy_class) {
2807                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2808                                 this = tp->rp->unwrapped_server;
2809                                 g_assert (this);
2810                                 k = this->vtable->klass;
2811                         }
2812                         
2813                         name = mono_array_get (params, MonoString *, 1);
2814                         str = mono_string_to_utf8 (name);
2815                 
2816                         do {
2817                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2818                                 if (field) {
2819                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2820                                         if (field_klass->valuetype)
2821                                                 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2822                                         else 
2823                                                 result = *((gpointer *)((char *)this + field->offset));
2824                                 
2825                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2826                                         *outArgs = out_args;
2827                                         mono_array_setref (out_args, 0, result);
2828                                         g_free (str);
2829                                         return NULL;
2830                                 }
2831                                 k = k->parent;
2832                         } while (k);
2833
2834                         g_free (str);
2835                         g_assert_not_reached ();
2836
2837                 } else if (!strcmp (m->name, "FieldSetter")) {
2838                         MonoClass *k = this->vtable->klass;
2839                         MonoString *name;
2840                         guint32 size;
2841                         gint32 align;
2842                         char *str;
2843                         
2844                         /* If this is a proxy, then it must be a CBO */
2845                         if (k == mono_defaults.transparent_proxy_class) {
2846                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2847                                 this = tp->rp->unwrapped_server;
2848                                 g_assert (this);
2849                                 k = this->vtable->klass;
2850                         }
2851                         
2852                         name = mono_array_get (params, MonoString *, 1);
2853                         str = mono_string_to_utf8 (name);
2854                 
2855                         do {
2856                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2857                                 if (field) {
2858                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2859                                         MonoObject *val = mono_array_get (params, gpointer, 2);
2860
2861                                         if (field_klass->valuetype) {
2862                                                 size = mono_type_size (field->type, &align);
2863                                                 memcpy ((char *)this + field->offset, 
2864                                                         ((char *)val) + sizeof (MonoObject), size);
2865                                         } else 
2866                                                 *(MonoObject**)((char *)this + field->offset) = val;
2867                                 
2868                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2869                                         *outArgs = out_args;
2870
2871                                         g_free (str);
2872                                         return NULL;
2873                                 }
2874                                 
2875                                 k = k->parent;
2876                         } while (k);
2877
2878                         g_free (str);
2879                         g_assert_not_reached ();
2880
2881                 }
2882         }
2883
2884         for (i = 0; i < mono_array_length (params); i++) {
2885                 if (sig->params [i]->byref) 
2886                         outarg_count++;
2887         }
2888
2889         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2890         
2891         /* handle constructors only for objects already allocated */
2892         if (!strcmp (method->method->name, ".ctor"))
2893                 g_assert (this);
2894
2895         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2896         g_assert (!method->method->klass->valuetype);
2897         result = mono_runtime_invoke_array (method->method, this, params, NULL);
2898
2899         for (i = 0, j = 0; i < mono_array_length (params); i++) {
2900                 if (sig->params [i]->byref) {
2901                         gpointer arg;
2902                         arg = mono_array_get (params, gpointer, i);
2903                         mono_array_setref (out_args, j, arg);
2904                         j++;
2905                 }
2906         }
2907
2908         *outArgs = out_args;
2909
2910         return result;
2911 }
2912
2913 static guint64
2914 read_enum_value (char *mem, int type)
2915 {
2916         switch (type) {
2917         case MONO_TYPE_U1:
2918                 return *(guint8*)mem;
2919         case MONO_TYPE_I1:
2920                 return *(gint8*)mem;
2921         case MONO_TYPE_U2:
2922                 return *(guint16*)mem;
2923         case MONO_TYPE_I2:
2924                 return *(gint16*)mem;
2925         case MONO_TYPE_U4:
2926                 return *(guint32*)mem;
2927         case MONO_TYPE_I4:
2928                 return *(gint32*)mem;
2929         case MONO_TYPE_U8:
2930                 return *(guint64*)mem;
2931         case MONO_TYPE_I8:
2932                 return *(gint64*)mem;
2933         default:
2934                 g_assert_not_reached ();
2935         }
2936         return 0;
2937 }
2938
2939 static void
2940 write_enum_value (char *mem, int type, guint64 value)
2941 {
2942         switch (type) {
2943         case MONO_TYPE_U1:
2944         case MONO_TYPE_I1: {
2945                 guint8 *p = (guint8*)mem;
2946                 *p = value;
2947                 break;
2948         }
2949         case MONO_TYPE_U2:
2950         case MONO_TYPE_I2: {
2951                 guint16 *p = (void*)mem;
2952                 *p = value;
2953                 break;
2954         }
2955         case MONO_TYPE_U4:
2956         case MONO_TYPE_I4: {
2957                 guint32 *p = (void*)mem;
2958                 *p = value;
2959                 break;
2960         }
2961         case MONO_TYPE_U8:
2962         case MONO_TYPE_I8: {
2963                 guint64 *p = (void*)mem;
2964                 *p = value;
2965                 break;
2966         }
2967         default:
2968                 g_assert_not_reached ();
2969         }
2970         return;
2971 }
2972
2973 static MonoObject *
2974 ves_icall_System_Enum_ToObject (MonoReflectionType *type, MonoObject *obj)
2975 {
2976         MonoDomain *domain; 
2977         MonoClass *enumc, *objc;
2978         MonoObject *res;
2979         guint64 val;
2980         
2981         MONO_ARCH_SAVE_REGS;
2982
2983         MONO_CHECK_ARG_NULL (type);
2984         MONO_CHECK_ARG_NULL (obj);
2985
2986         domain = mono_object_domain (type); 
2987         enumc = mono_class_from_mono_type (type->type);
2988         objc = obj->vtable->klass;
2989
2990         if (!enumc->enumtype)
2991                 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
2992         if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
2993                 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
2994
2995         res = mono_object_new (domain, enumc);
2996         val = read_enum_value ((char *)obj + sizeof (MonoObject), objc->enumtype? objc->enum_basetype->type: objc->byval_arg.type);
2997         write_enum_value ((char *)res + sizeof (MonoObject), enumc->enum_basetype->type, val);
2998
2999         return res;
3000 }
3001
3002 static MonoObject *
3003 ves_icall_System_Enum_get_value (MonoObject *this)
3004 {
3005         MonoObject *res;
3006         MonoClass *enumc;
3007         gpointer dst;
3008         gpointer src;
3009         int size;
3010
3011         MONO_ARCH_SAVE_REGS;
3012
3013         if (!this)
3014                 return NULL;
3015
3016         g_assert (this->vtable->klass->enumtype);
3017         
3018         enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
3019         res = mono_object_new (mono_object_domain (this), enumc);
3020         dst = (char *)res + sizeof (MonoObject);
3021         src = (char *)this + sizeof (MonoObject);
3022         size = mono_class_value_size (enumc, NULL);
3023
3024         memcpy (dst, src, size);
3025
3026         return res;
3027 }
3028
3029 static void
3030 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3031 {
3032         MonoDomain *domain = mono_object_domain (type); 
3033         MonoClass *enumc = mono_class_from_mono_type (type->type);
3034         guint j = 0, nvalues, crow;
3035         gpointer iter;
3036         MonoClassField *field;
3037
3038         MONO_ARCH_SAVE_REGS;
3039
3040         info->utype = mono_type_get_object (domain, enumc->enum_basetype);
3041         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3042         info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3043         info->values = mono_array_new (domain, enumc, nvalues);
3044         
3045         crow = -1;
3046         iter = NULL;
3047         while ((field = mono_class_get_fields (enumc, &iter))) {
3048                 const char *p;
3049                 int len;
3050                 
3051                 if (strcmp ("value__", field->name) == 0)
3052                         continue;
3053                 if (mono_field_is_deleted (field))
3054                         continue;
3055                 mono_array_setref (info->names, j, mono_string_new (domain, field->name));
3056
3057                 if (!field->data) {
3058                         crow = mono_metadata_get_constant_index (enumc->image, mono_class_get_field_token (field), crow + 1);
3059                         field->def_type = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_TYPE);
3060                         crow = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_VALUE);
3061                         field->data = (gpointer)mono_metadata_blob_heap (enumc->image, crow);
3062                 }
3063
3064                 p = field->data;
3065                 len = mono_metadata_decode_blob_size (p, &p);
3066                 switch (enumc->enum_basetype->type) {
3067                 case MONO_TYPE_U1:
3068                 case MONO_TYPE_I1:
3069                         mono_array_set (info->values, gchar, j, *p);
3070                         break;
3071                 case MONO_TYPE_CHAR:
3072                 case MONO_TYPE_U2:
3073                 case MONO_TYPE_I2:
3074                         mono_array_set (info->values, gint16, j, read16 (p));
3075                         break;
3076                 case MONO_TYPE_U4:
3077                 case MONO_TYPE_I4:
3078                         mono_array_set (info->values, gint32, j, read32 (p));
3079                         break;
3080                 case MONO_TYPE_U8:
3081                 case MONO_TYPE_I8:
3082                         mono_array_set (info->values, gint64, j, read64 (p));
3083                         break;
3084                 default:
3085                         g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
3086                 }
3087                 ++j;
3088         }
3089 }
3090
3091 enum {
3092         BFLAGS_IgnoreCase = 1,
3093         BFLAGS_DeclaredOnly = 2,
3094         BFLAGS_Instance = 4,
3095         BFLAGS_Static = 8,
3096         BFLAGS_Public = 0x10,
3097         BFLAGS_NonPublic = 0x20,
3098         BFLAGS_FlattenHierarchy = 0x40,
3099         BFLAGS_InvokeMethod = 0x100,
3100         BFLAGS_CreateInstance = 0x200,
3101         BFLAGS_GetField = 0x400,
3102         BFLAGS_SetField = 0x800,
3103         BFLAGS_GetProperty = 0x1000,
3104         BFLAGS_SetProperty = 0x2000,
3105         BFLAGS_ExactBinding = 0x10000,
3106         BFLAGS_SuppressChangeType = 0x20000,
3107         BFLAGS_OptionalParamBinding = 0x40000
3108 };
3109
3110 static MonoReflectionField *
3111 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3112 {
3113         MonoDomain *domain; 
3114         MonoClass *startklass, *klass;
3115         int match;
3116         MonoClassField *field;
3117         gpointer iter;
3118         char *utf8_name;
3119         int (*compare_func) (const char *s1, const char *s2) = NULL;
3120         domain = ((MonoObject *)type)->vtable->domain;
3121         klass = startklass = mono_class_from_mono_type (type->type);
3122
3123         MONO_ARCH_SAVE_REGS;
3124
3125         if (!name)
3126                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3127         if (type->type->byref)
3128                 return NULL;
3129
3130         compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3131
3132 handle_parent:
3133         if (klass->exception_type != MONO_EXCEPTION_NONE)
3134                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3135
3136         iter = NULL;
3137         while ((field = mono_class_get_fields (klass, &iter))) {
3138                 match = 0;
3139
3140                 if (field->type == NULL)
3141                         continue;
3142                 if (mono_field_is_deleted (field))
3143                         continue;
3144                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3145                         if (bflags & BFLAGS_Public)
3146                                 match++;
3147                 } else {
3148                         if (bflags & BFLAGS_NonPublic)
3149                                 match++;
3150                 }
3151                 if (!match)
3152                         continue;
3153                 match = 0;
3154                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3155                         if (bflags & BFLAGS_Static)
3156                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3157                                         match++;
3158                 } else {
3159                         if (bflags & BFLAGS_Instance)
3160                                 match++;
3161                 }
3162
3163                 if (!match)
3164                         continue;
3165                 
3166                 utf8_name = mono_string_to_utf8 (name);
3167
3168                 if (compare_func (field->name, utf8_name)) {
3169                         g_free (utf8_name);
3170                         continue;
3171                 }
3172                 g_free (utf8_name);
3173                 
3174                 return mono_field_get_object (domain, klass, field);
3175         }
3176         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3177                 goto handle_parent;
3178
3179         return NULL;
3180 }
3181
3182 static MonoArray*
3183 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3184 {
3185         MonoDomain *domain; 
3186         MonoClass *startklass, *klass, *refklass;
3187         MonoArray *res;
3188         MonoObject *member;
3189         int i, len, match;
3190         gpointer iter;
3191         MonoClassField *field;
3192
3193         MONO_ARCH_SAVE_REGS;
3194
3195         domain = ((MonoObject *)type)->vtable->domain;
3196         if (type->type->byref)
3197                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3198         klass = startklass = mono_class_from_mono_type (type->type);
3199         refklass = mono_class_from_mono_type (reftype->type);
3200
3201         i = 0;
3202         len = 2;
3203         res = mono_array_new (domain, mono_defaults.field_info_class, len);
3204 handle_parent:  
3205         if (klass->exception_type != MONO_EXCEPTION_NONE)
3206                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3207
3208         iter = NULL;
3209         while ((field = mono_class_get_fields (klass, &iter))) {
3210                 match = 0;
3211                 if (mono_field_is_deleted (field))
3212                         continue;
3213                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3214                         if (bflags & BFLAGS_Public)
3215                                 match++;
3216                 } else {
3217                         if (bflags & BFLAGS_NonPublic) {
3218                                 /* Serialization currently depends on the old behavior.
3219                                  * if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE || startklass == klass)*/
3220                                         match++;
3221                         }
3222                 }
3223                 if (!match)
3224                         continue;
3225                 match = 0;
3226                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3227                         if (bflags & BFLAGS_Static)
3228                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3229                                         match++;
3230                 } else {
3231                         if (bflags & BFLAGS_Instance)
3232                                 match++;
3233                 }
3234
3235                 if (!match)
3236                         continue;
3237                 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3238                 if (i >= len) {
3239                         MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3240                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3241                         len *= 2;
3242                         res = new_res;
3243                 }
3244                 mono_array_setref (res, i, member);
3245                 ++i;
3246         }
3247         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3248                 goto handle_parent;
3249         if (i != len) {
3250                 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3251                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3252                 res = new_res;
3253                 /*
3254                  * Better solution for the new GC.
3255                  * res->max_length = i;
3256                  */
3257         }
3258         return res;
3259 }
3260
3261 static MonoArray*
3262 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3263 {
3264         MonoDomain *domain; 
3265         MonoClass *startklass, *klass, *refklass;
3266         MonoArray *res;
3267         MonoMethod *method;
3268         gpointer iter;
3269         MonoObject *member;
3270         int i, len, match, nslots;
3271         guint32 method_slots_default [8];
3272         guint32 *method_slots;
3273         gchar *mname = NULL;
3274         int (*compare_func) (const char *s1, const char *s2) = NULL;
3275                 
3276         MONO_ARCH_SAVE_REGS;
3277
3278         domain = ((MonoObject *)type)->vtable->domain;
3279         if (type->type->byref)
3280                 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3281         klass = startklass = mono_class_from_mono_type (type->type);
3282         refklass = mono_class_from_mono_type (reftype->type);
3283         len = 0;
3284         if (name != NULL) {
3285                 mname = mono_string_to_utf8 (name);
3286                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3287         }
3288
3289         mono_class_setup_vtable (klass);
3290
3291         if (is_generic_parameter (type->type))
3292                 nslots = klass->parent->vtable_size;
3293         else
3294                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3295         if (nslots >= sizeof (method_slots_default) * 8) {
3296                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3297         } else {
3298                 method_slots = method_slots_default;
3299                 memset (method_slots, 0, sizeof (method_slots_default));
3300         }
3301         i = 0;
3302         len = 1;
3303         res = mono_array_new (domain, mono_defaults.method_info_class, len);
3304 handle_parent:
3305         mono_class_setup_vtable (klass);
3306         if (klass->exception_type != MONO_EXCEPTION_NONE)
3307                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3308
3309         iter = NULL;
3310         while ((method = mono_class_get_methods (klass, &iter))) {
3311                 match = 0;
3312                 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3313                         continue;
3314                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3315                         if (bflags & BFLAGS_Public)
3316                                 match++;
3317                 } else {
3318                         if (bflags & BFLAGS_NonPublic)
3319                                 match++;
3320                 }
3321                 if (!match)
3322                         continue;
3323                 match = 0;
3324                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3325                         if (bflags & BFLAGS_Static)
3326                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3327                                         match++;
3328                 } else {
3329                         if (bflags & BFLAGS_Instance)
3330                                 match++;
3331                 }
3332
3333                 if (!match)
3334                         continue;
3335
3336                 if (name != NULL) {
3337                         if (compare_func (mname, method->name))
3338                                 continue;
3339                 }
3340                 
3341                 match = 0;
3342                 if (method->slot != -1) {
3343                         g_assert (method->slot < nslots);
3344                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3345                                 continue;
3346                         method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3347                 }
3348                 
3349                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3350                 
3351                 if (i >= len) {
3352                         MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, len * 2);
3353                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3354                         len *= 2;
3355                         res = new_res;
3356                 }
3357                 mono_array_setref (res, i, member);
3358                 ++i;
3359         }
3360         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3361                 goto handle_parent;
3362
3363         g_free (mname);
3364         if (method_slots != method_slots_default)
3365                 g_free (method_slots);
3366         if (i != len) {
3367                 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3368                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3369                 res = new_res;
3370                 /*
3371                  * Better solution for the new GC.
3372                  * res->max_length = i;
3373                  */
3374         }
3375         return res;
3376 }
3377
3378 static MonoArray*
3379 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3380 {
3381         MonoDomain *domain; 
3382         static MonoClass *System_Reflection_ConstructorInfo;
3383         MonoClass *startklass, *klass, *refklass;
3384         MonoArray *res;
3385         MonoMethod *method;
3386         MonoObject *member;
3387         int i, len, match;
3388         gpointer iter = NULL;
3389         
3390         MONO_ARCH_SAVE_REGS;
3391
3392         domain = ((MonoObject *)type)->vtable->domain;
3393         if (type->type->byref)
3394                 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3395         klass = startklass = mono_class_from_mono_type (type->type);
3396         refklass = mono_class_from_mono_type (reftype->type);
3397
3398         if (klass->exception_type != MONO_EXCEPTION_NONE)
3399                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3400
3401         if (!System_Reflection_ConstructorInfo)
3402                 System_Reflection_ConstructorInfo = mono_class_from_name (
3403                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3404
3405         i = 0;
3406         len = 2;
3407         res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3408         iter = NULL;
3409         while ((method = mono_class_get_methods (klass, &iter))) {
3410                 match = 0;
3411                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3412                         continue;
3413                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3414                         if (bflags & BFLAGS_Public)
3415                                 match++;
3416                 } else {
3417                         if (bflags & BFLAGS_NonPublic)
3418                                 match++;
3419                 }
3420                 if (!match)
3421                         continue;
3422                 match = 0;
3423                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3424                         if (bflags & BFLAGS_Static)
3425                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3426                                         match++;
3427                 } else {
3428                         if (bflags & BFLAGS_Instance)
3429                                 match++;
3430                 }
3431
3432                 if (!match)
3433                         continue;
3434                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3435
3436                 if (i >= len) {
3437                         MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3438                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3439                         len *= 2;
3440                         res = new_res;
3441                 }
3442                 mono_array_setref (res, i, member);
3443                 ++i;
3444         }
3445         if (i != len) {
3446                 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3447                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3448                 res = new_res;
3449                 /*
3450                  * Better solution for the new GC.
3451                  * res->max_length = i;
3452                  */
3453         }
3454         return res;
3455 }
3456
3457 static MonoArray*
3458 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3459 {
3460         MonoDomain *domain; 
3461         static MonoClass *System_Reflection_PropertyInfo;
3462         MonoClass *startklass, *klass;
3463         MonoArray *res;
3464         MonoMethod *method;
3465         MonoProperty *prop;
3466         int i, match, nslots;
3467         int len = 0;
3468         guint32 flags;
3469         guint32 method_slots_default [8];
3470         guint32 *method_slots;
3471         gchar *propname = NULL;
3472         int (*compare_func) (const char *s1, const char *s2) = NULL;
3473         gpointer iter;
3474
3475         MONO_ARCH_SAVE_REGS;
3476
3477         if (!System_Reflection_PropertyInfo)
3478                 System_Reflection_PropertyInfo = mono_class_from_name (
3479                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3480
3481         domain = ((MonoObject *)type)->vtable->domain;
3482         if (type->type->byref)
3483                 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3484         klass = startklass = mono_class_from_mono_type (type->type);
3485         if (name != NULL) {
3486                 propname = mono_string_to_utf8 (name);
3487                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3488         }
3489
3490         mono_class_setup_vtable (klass);
3491
3492         nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3493         if (nslots >= sizeof (method_slots_default) * 8) {
3494                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3495         } else {
3496                 method_slots = method_slots_default;
3497                 memset (method_slots, 0, sizeof (method_slots_default));
3498         }
3499         i = 0;
3500         len = 2;
3501         res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3502 handle_parent:
3503         mono_class_setup_vtable (klass);
3504         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3505                 if (method_slots != method_slots_default)
3506                         g_free (method_slots);
3507                 if (name != NULL)
3508                         g_free (propname);
3509                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3510         }
3511
3512         iter = NULL;
3513         while ((prop = mono_class_get_properties (klass, &iter))) {
3514                 match = 0;
3515                 method = prop->get;
3516                 if (!method)
3517                         method = prop->set;
3518                 if (method)
3519                         flags = method->flags;
3520                 else
3521                         flags = 0;
3522                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3523                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3524                         if (bflags & BFLAGS_Public)
3525                                 match++;
3526                 } else {
3527                         if (bflags & BFLAGS_NonPublic)
3528                                 match++;
3529                 }
3530                 if (!match)
3531                         continue;
3532                 match = 0;
3533                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3534                         if (bflags & BFLAGS_Static)
3535                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3536                                         match++;
3537                 } else {
3538                         if (bflags & BFLAGS_Instance)
3539                                 match++;
3540                 }
3541
3542                 if (!match)
3543                         continue;
3544                 match = 0;
3545
3546                 if (name != NULL) {
3547                         if (compare_func (propname, prop->name))
3548                                 continue;
3549                 }
3550                 
3551                 if (prop->get && prop->get->slot != -1) {
3552                         if (method_slots [prop->get->slot >> 5] & (1 << (prop->get->slot & 0x1f)))
3553                                 continue;
3554                         method_slots [prop->get->slot >> 5] |= 1 << (prop->get->slot & 0x1f);
3555                 }
3556                 if (prop->set && prop->set->slot != -1) {
3557                         if (method_slots [prop->set->slot >> 5] & (1 << (prop->set->slot & 0x1f)))
3558                                 continue;
3559                         method_slots [prop->set->slot >> 5] |= 1 << (prop->set->slot & 0x1f);
3560                 }
3561
3562                 if (i >= len) {
3563                         MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3564                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3565                         len *= 2;
3566                         res = new_res;
3567                 }
3568                 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3569                 ++i;
3570         }
3571         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3572                 goto handle_parent;
3573
3574         g_free (propname);
3575         if (method_slots != method_slots_default)
3576                 g_free (method_slots);
3577         if (i != len) {
3578                 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3579                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3580                 res = new_res;
3581                 /*
3582                  * Better solution for the new GC.
3583                  * res->max_length = i;
3584                  */
3585         }
3586         return res;
3587 }
3588
3589 static MonoReflectionEvent *
3590 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3591 {
3592         MonoDomain *domain;
3593         MonoClass *klass, *startklass;
3594         gpointer iter;
3595         MonoEvent *event;
3596         MonoMethod *method;
3597         gchar *event_name;
3598
3599         MONO_ARCH_SAVE_REGS;
3600
3601         event_name = mono_string_to_utf8 (name);
3602         if (type->type->byref)
3603                 return NULL;
3604         klass = startklass = mono_class_from_mono_type (type->type);
3605         domain = mono_object_domain (type);
3606
3607 handle_parent:  
3608         if (klass->exception_type != MONO_EXCEPTION_NONE)
3609                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3610
3611         iter = NULL;
3612         while ((event = mono_class_get_events (klass, &iter))) {
3613                 if (strcmp (event->name, event_name))
3614                         continue;
3615
3616                 method = event->add;
3617                 if (!method)
3618                         method = event->remove;
3619                 if (!method)
3620                         method = event->raise;
3621                 if (method) {
3622                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3623                                 if (!(bflags & BFLAGS_Public))
3624                                         continue;
3625                         } else {
3626                                 if (!(bflags & BFLAGS_NonPublic))
3627                                         continue;
3628                         }
3629                 }
3630                 else
3631                         if (!(bflags & BFLAGS_NonPublic))
3632                                 continue;
3633
3634                 g_free (event_name);
3635                 return mono_event_get_object (domain, startklass, event);
3636         }
3637
3638         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3639                 goto handle_parent;
3640
3641         g_free (event_name);
3642         return NULL;
3643 }
3644
3645 static MonoArray*
3646 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3647 {
3648         MonoDomain *domain; 
3649         static MonoClass *System_Reflection_EventInfo;
3650         MonoClass *startklass, *klass;
3651         MonoArray *res;
3652         MonoMethod *method;
3653         MonoEvent *event;
3654         int i, len, match;
3655         gpointer iter;
3656
3657         MONO_ARCH_SAVE_REGS;
3658
3659         if (!System_Reflection_EventInfo)
3660                 System_Reflection_EventInfo = mono_class_from_name (
3661                         mono_defaults.corlib, "System.Reflection", "EventInfo");
3662
3663         domain = mono_object_domain (type);
3664         if (type->type->byref)
3665                 return mono_array_new (domain, System_Reflection_EventInfo, 0);
3666         klass = startklass = mono_class_from_mono_type (type->type);
3667
3668         i = 0;
3669         len = 2;
3670         res = mono_array_new (domain, System_Reflection_EventInfo, len);
3671 handle_parent:  
3672         if (klass->exception_type != MONO_EXCEPTION_NONE)
3673                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3674
3675         iter = NULL;
3676         while ((event = mono_class_get_events (klass, &iter))) {
3677                 match = 0;
3678                 method = event->add;
3679                 if (!method)
3680                         method = event->remove;
3681                 if (!method)
3682                         method = event->raise;
3683                 if (method) {
3684                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3685                                 if (bflags & BFLAGS_Public)
3686                                         match++;
3687                         } else {
3688                                 if (bflags & BFLAGS_NonPublic)
3689                                         match++;
3690                         }
3691                 }
3692                 else
3693                         if (bflags & BFLAGS_NonPublic)
3694                                 match ++;
3695                 if (!match)
3696                         continue;
3697                 match = 0;
3698                 if (method) {
3699                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3700                                 if (bflags & BFLAGS_Static)
3701                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3702                                                 match++;
3703                         } else {
3704                                 if (bflags & BFLAGS_Instance)
3705                                         match++;
3706                         }
3707                 }
3708                 else
3709                         if (bflags & BFLAGS_Instance)
3710                                 match ++;
3711                 if (!match)
3712                         continue;
3713                 match = 0;
3714                 if (i >= len) {
3715                         MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
3716                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3717                         len *= 2;
3718                         res = new_res;
3719                 }
3720                 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
3721                 ++i;
3722         }
3723         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3724                 goto handle_parent;
3725         if (i != len) {
3726                 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
3727                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3728                 res = new_res;
3729                 /*
3730                  * Better solution for the new GC.
3731                  * res->max_length = i;
3732                  */
3733         }
3734         return res;
3735 }
3736
3737 static MonoReflectionType *
3738 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3739 {
3740         MonoDomain *domain; 
3741         MonoClass *klass;
3742         MonoClass *nested;
3743         GList *tmpn;
3744         char *str;
3745         
3746         MONO_ARCH_SAVE_REGS;
3747
3748         domain = ((MonoObject *)type)->vtable->domain;
3749         if (type->type->byref)
3750                 return NULL;
3751         klass = mono_class_from_mono_type (type->type);
3752         str = mono_string_to_utf8 (name);
3753
3754  handle_parent:
3755         if (klass->exception_type != MONO_EXCEPTION_NONE)
3756                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3757
3758         /*
3759          * If a nested type is generic, return its generic type definition.
3760          * Note that this means that the return value is essentially a
3761          * nested type of the generic type definition of @klass.
3762          *
3763          * A note in MSDN claims that a generic type definition can have
3764          * nested types that aren't generic.  In any case, the container of that
3765          * nested type would be the generic type definition.
3766          */
3767         if (klass->generic_class)
3768                 klass = klass->generic_class->container_class;
3769
3770         for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3771                 int match = 0;
3772                 nested = tmpn->data;
3773                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3774                         if (bflags & BFLAGS_Public)
3775                                 match++;
3776                 } else {
3777                         if (bflags & BFLAGS_NonPublic)
3778                                 match++;
3779                 }
3780                 if (!match)
3781                         continue;
3782                 if (strcmp (nested->name, str) == 0){
3783                         g_free (str);
3784                         return mono_type_get_object (domain, &nested->byval_arg);
3785                 }
3786         }
3787         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3788                 goto handle_parent;
3789         g_free (str);
3790         return NULL;
3791 }
3792
3793 static MonoArray*
3794 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3795 {
3796         MonoDomain *domain; 
3797         GList *tmpn;
3798         MonoClass *klass;
3799         MonoArray *res;
3800         MonoObject *member;
3801         int i, len, match;
3802         MonoClass *nested;
3803
3804         MONO_ARCH_SAVE_REGS;
3805
3806         domain = ((MonoObject *)type)->vtable->domain;
3807         if (type->type->byref)
3808                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3809         klass = mono_class_from_mono_type (type->type);
3810         if (klass->exception_type != MONO_EXCEPTION_NONE)
3811                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3812
3813         /*
3814          * If a nested type is generic, return its generic type definition.
3815          * Note that this means that the return value is essentially the set
3816          * of nested types of the generic type definition of @klass.
3817          *
3818          * A note in MSDN claims that a generic type definition can have
3819          * nested types that aren't generic.  In any case, the container of that
3820          * nested type would be the generic type definition.
3821          */
3822         if (klass->generic_class)
3823                 klass = klass->generic_class->container_class;
3824
3825         i = 0;
3826         len = 1;
3827         res = mono_array_new (domain, mono_defaults.monotype_class, len);
3828         for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3829                 match = 0;
3830                 nested = tmpn->data;
3831                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3832                         if (bflags & BFLAGS_Public)
3833                                 match++;
3834                 } else {
3835                         if (bflags & BFLAGS_NonPublic)
3836                                 match++;
3837                 }
3838                 if (!match)
3839                         continue;
3840                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3841                 if (i >= len) {
3842                         MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
3843                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3844                         len *= 2;
3845                         res = new_res;
3846                 }
3847                 mono_array_setref (res, i, member);
3848                 ++i;
3849         }
3850         if (i != len) {
3851                 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
3852                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3853                 res = new_res;
3854                 /*
3855                  * Better solution for the new GC.
3856                  * res->max_length = i;
3857                  */
3858         }
3859         return res;
3860 }
3861
3862 static MonoReflectionType*
3863 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3864 {
3865         gchar *str;
3866         MonoType *type = NULL;
3867         MonoTypeNameParse info;
3868         gboolean type_resolve;
3869
3870         MONO_ARCH_SAVE_REGS;
3871
3872         /* On MS.NET, this does not fire a TypeResolve event */
3873         type_resolve = TRUE;
3874         str = mono_string_to_utf8 (name);
3875         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3876         if (!mono_reflection_parse_type (str, &info)) {
3877                 g_free (str);
3878                 mono_reflection_free_type_info (&info);
3879                 if (throwOnError) /* uhm: this is a parse error, though... */
3880                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
3881                 /*g_print ("failed parse\n");*/
3882                 return NULL;
3883         }
3884
3885         if (module != NULL) {
3886                 if (module->image)
3887                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
3888                 else
3889                         type = NULL;
3890         }
3891         else
3892                 if (assembly->assembly->dynamic) {
3893                         /* Enumerate all modules */
3894                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
3895                         int i;
3896
3897                         type = NULL;
3898                         if (abuilder->modules) {
3899                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
3900                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
3901                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
3902                                         if (type)
3903                                                 break;
3904                                 }
3905                         }
3906
3907                         if (!type && abuilder->loaded_modules) {
3908                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
3909                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
3910                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
3911                                         if (type)
3912                                                 break;
3913                                 }
3914                         }
3915                 }
3916                 else
3917                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
3918         g_free (str);
3919         mono_reflection_free_type_info (&info);
3920         if (!type) {
3921                 MonoException *e = NULL;
3922                 
3923                 if (throwOnError)
3924                         e = mono_get_exception_type_load (name, NULL);
3925
3926                 mono_loader_clear_error ();
3927
3928                 if (e != NULL)
3929                         mono_raise_exception (e);
3930
3931                 return NULL;
3932         }
3933
3934         if (type->type == MONO_TYPE_CLASS) {
3935                 MonoClass *klass = mono_type_get_class (type);
3936                 /* need to report exceptions ? */
3937                 if (throwOnError && klass->exception_type) {
3938                         /* report SecurityException (or others) that occured when loading the assembly */
3939                         MonoException *exc = mono_class_get_exception_for_failure (klass);
3940                         mono_loader_clear_error ();
3941                         mono_raise_exception (exc);
3942                 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
3943                         return NULL;
3944                 }
3945         }
3946
3947         /* g_print ("got it\n"); */
3948         return mono_type_get_object (mono_object_domain (assembly), type);
3949 }
3950
3951 static MonoString *
3952 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
3953 {
3954         MonoDomain *domain = mono_object_domain (assembly); 
3955         MonoAssembly *mass = assembly->assembly;
3956         MonoString *res = NULL;
3957         gchar *uri;
3958         gchar *absolute;
3959         
3960         MONO_ARCH_SAVE_REGS;
3961
3962         if (g_path_is_absolute (mass->image->name))
3963                 absolute = g_strdup (mass->image->name);
3964         else
3965                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
3966 #if PLATFORM_WIN32
3967         {
3968                 gint i;
3969                 for (i = strlen (absolute) - 1; i >= 0; i--)
3970                         if (absolute [i] == '\\')
3971                                 absolute [i] = '/';
3972         }
3973 #endif
3974         if (escaped) {
3975                 uri = g_filename_to_uri (absolute, NULL, NULL);
3976         } else {
3977                 uri = g_strconcat ("file://", absolute, NULL);
3978         }
3979
3980         if (uri) {
3981                 res = mono_string_new (domain, uri);
3982                 g_free (uri);
3983         }
3984         g_free (absolute);
3985         return res;
3986 }
3987
3988 static MonoBoolean
3989 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
3990 {
3991         MonoAssembly *mass = assembly->assembly;
3992
3993         MONO_ARCH_SAVE_REGS;
3994
3995         return mass->in_gac;
3996 }
3997
3998 static MonoReflectionAssembly*
3999 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4000 {
4001         gchar *name;
4002         MonoAssembly *res;
4003         MonoImageOpenStatus status;
4004         
4005         MONO_ARCH_SAVE_REGS;
4006
4007         name = mono_string_to_utf8 (mname);
4008         res = mono_assembly_load_with_partial_name (name, &status);
4009
4010         g_free (name);
4011
4012         if (res == NULL)
4013                 return NULL;
4014         return mono_assembly_get_object (mono_domain_get (), res);
4015 }
4016
4017 static MonoString *
4018 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4019 {
4020         MonoDomain *domain = mono_object_domain (assembly); 
4021         MonoString *res;
4022
4023         MONO_ARCH_SAVE_REGS;
4024
4025         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4026
4027         return res;
4028 }
4029
4030 static MonoBoolean
4031 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4032 {
4033         MONO_ARCH_SAVE_REGS;
4034
4035         return assembly->assembly->ref_only;
4036 }
4037
4038 static MonoString *
4039 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4040 {
4041         MonoDomain *domain = mono_object_domain (assembly); 
4042
4043         MONO_ARCH_SAVE_REGS;
4044
4045         return mono_string_new (domain, assembly->assembly->image->version);
4046 }
4047
4048 static MonoReflectionMethod*
4049 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4050 {
4051         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4052
4053         MONO_ARCH_SAVE_REGS;
4054
4055         if (!token)
4056                 return NULL;
4057         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4058 }
4059
4060 static MonoReflectionModule*
4061 ves_icall_System_Reflection_Assembly_get_ManifestModule (MonoReflectionAssembly *assembly) 
4062 {
4063         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4064 }
4065
4066 static MonoArray*
4067 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4068 {
4069         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4070         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4071         int i;
4072         const char *val;
4073
4074         MONO_ARCH_SAVE_REGS;
4075
4076         for (i = 0; i < table->rows; ++i) {
4077                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4078                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4079         }
4080         return result;
4081 }
4082
4083 static MonoObject*
4084 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4085 {
4086         static MonoClass *System_Version = NULL;
4087         static MonoMethod *create_version = NULL;
4088         MonoObject *result;
4089         gpointer args [4];
4090         
4091         if (!System_Version) {
4092                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4093                 g_assert (System_Version);
4094         }
4095
4096         if (!create_version) {
4097                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4098                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4099                 g_assert (create_version);
4100                 mono_method_desc_free (desc);
4101         }
4102
4103         args [0] = &major;
4104         args [1] = &minor;
4105         args [2] = &build;
4106         args [3] = &revision;
4107         result = mono_object_new (domain, System_Version);
4108         mono_runtime_invoke (create_version, result, args, NULL);
4109
4110         return result;
4111 }
4112
4113 static MonoArray*
4114 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4115 {
4116         static MonoClass *System_Reflection_AssemblyName;
4117         MonoArray *result;
4118         MonoDomain *domain = mono_object_domain (assembly);
4119         int i, count = 0;
4120         static MonoMethod *create_culture = NULL;
4121         MonoImage *image = assembly->assembly->image;
4122         MonoTableInfo *t;
4123
4124         MONO_ARCH_SAVE_REGS;
4125
4126         if (!System_Reflection_AssemblyName)
4127                 System_Reflection_AssemblyName = mono_class_from_name (
4128                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4129
4130         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4131         count = t->rows;
4132
4133         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4134
4135         if (count > 0) {
4136                 MonoMethodDesc *desc = mono_method_desc_new (
4137                         "System.Globalization.CultureInfo:CreateSpecificCulture(string)", TRUE);
4138                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4139                 g_assert (create_culture);
4140                 mono_method_desc_free (desc);
4141         }
4142
4143         for (i = 0; i < count; i++) {
4144                 MonoReflectionAssemblyName *aname;
4145                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4146
4147                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4148
4149                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4150                         domain, System_Reflection_AssemblyName);
4151
4152                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4153
4154                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4155                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4156                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4157                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4158                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4159                 aname->versioncompat = 1; /* SameMachine (default) */
4160                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4161                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4162
4163                 if (create_culture) {
4164                         gpointer args [1];
4165                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4166                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4167                 }
4168                 
4169                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4170                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4171                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4172
4173                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4174                                 /* public key token isn't copied - the class library will 
4175                                 automatically generate it from the public key if required */
4176                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4177                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4178                         } else {
4179                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4180                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4181                         }
4182                 }
4183                 
4184                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4185                          be used under partial trust as path information isn't present). */
4186
4187                 mono_array_setref (result, i, aname);
4188         }
4189         return result;
4190 }
4191
4192 typedef struct {
4193         MonoArray *res;
4194         int idx;
4195 } NameSpaceInfo;
4196
4197 static void
4198 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4199 {
4200         MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4201
4202         mono_array_setref (info->res, info->idx, name);
4203         info->idx++;
4204 }
4205
4206 static MonoArray*
4207 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
4208 {
4209         MonoImage *img = assembly->assembly->image;
4210         MonoArray *res;
4211         NameSpaceInfo info;
4212
4213         MONO_ARCH_SAVE_REGS;
4214
4215         if (!img->name_cache)
4216                 mono_image_init_name_cache (img);
4217
4218         res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4219         info.res = res;
4220         info.idx = 0;
4221         g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4222
4223         return res;
4224 }
4225
4226 /* move this in some file in mono/util/ */
4227 static char *
4228 g_concat_dir_and_file (const char *dir, const char *file)
4229 {
4230         g_return_val_if_fail (dir != NULL, NULL);
4231         g_return_val_if_fail (file != NULL, NULL);
4232
4233         /*
4234          * If the directory name doesn't have a / on the end, we need
4235          * to add one so we get a proper path to the file
4236          */
4237         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4238                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4239         else
4240                 return g_strconcat (dir, file, NULL);
4241 }
4242
4243 static void *
4244 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4245 {
4246         char *n = mono_string_to_utf8 (name);
4247         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4248         guint32 i;
4249         guint32 cols [MONO_MANIFEST_SIZE];
4250         guint32 impl, file_idx;
4251         const char *val;
4252         MonoImage *module;
4253
4254         MONO_ARCH_SAVE_REGS;
4255
4256         for (i = 0; i < table->rows; ++i) {
4257                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4258                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4259                 if (strcmp (val, n) == 0)
4260                         break;
4261         }
4262         g_free (n);
4263         if (i == table->rows)
4264                 return NULL;
4265         /* FIXME */
4266         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4267         if (impl) {
4268                 /*
4269                  * this code should only be called after obtaining the 
4270                  * ResourceInfo and handling the other cases.
4271                  */
4272                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4273                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4274
4275                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4276                 if (!module)
4277                         return NULL;
4278         }
4279         else
4280                 module = assembly->assembly->image;
4281
4282         *ref_module = mono_module_get_object (mono_domain_get (), module);
4283
4284         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4285 }
4286
4287 static gboolean
4288 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4289 {
4290         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4291         int i;
4292         guint32 cols [MONO_MANIFEST_SIZE];
4293         guint32 file_cols [MONO_FILE_SIZE];
4294         const char *val;
4295         char *n;
4296
4297         MONO_ARCH_SAVE_REGS;
4298
4299         n = mono_string_to_utf8 (name);
4300         for (i = 0; i < table->rows; ++i) {
4301                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4302                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4303                 if (strcmp (val, n) == 0)
4304                         break;
4305         }
4306         g_free (n);
4307         if (i == table->rows)
4308                 return FALSE;
4309
4310         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4311                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4312         }
4313         else {
4314                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4315                 case MONO_IMPLEMENTATION_FILE:
4316                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4317                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4318                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4319                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4320                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4321                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4322                                 info->location = 0;
4323                         else
4324                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4325                         break;
4326
4327                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4328                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4329                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4330                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4331                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4332                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4333                                 g_free (msg);
4334                                 mono_raise_exception (ex);
4335                         }
4336                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4337
4338                         /* Obtain info recursively */
4339                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4340                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4341                         break;
4342
4343                 case MONO_IMPLEMENTATION_EXP_TYPE:
4344                         g_assert_not_reached ();
4345                         break;
4346                 }
4347         }
4348
4349         return TRUE;
4350 }
4351
4352 static MonoObject*
4353 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4354 {
4355         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4356         MonoArray *result = NULL;
4357         int i, count;
4358         const char *val;
4359         char *n;
4360
4361         MONO_ARCH_SAVE_REGS;
4362
4363         /* check hash if needed */
4364         if (name) {
4365                 n = mono_string_to_utf8 (name);
4366                 for (i = 0; i < table->rows; ++i) {
4367                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4368                         if (strcmp (val, n) == 0) {
4369                                 MonoString *fn;
4370                                 g_free (n);
4371                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4372                                 fn = mono_string_new (mono_object_domain (assembly), n);
4373                                 g_free (n);
4374                                 return (MonoObject*)fn;
4375                         }
4376                 }
4377                 g_free (n);
4378                 return NULL;
4379         }
4380
4381         count = 0;
4382         for (i = 0; i < table->rows; ++i) {
4383                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4384                         count ++;
4385         }
4386
4387         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4388
4389         count = 0;
4390         for (i = 0; i < table->rows; ++i) {
4391                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4392                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4393                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4394                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4395                         g_free (n);
4396                         count ++;
4397                 }
4398         }
4399         return (MonoObject*)result;
4400 }
4401
4402 static MonoArray*
4403 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4404 {
4405         MonoDomain *domain = mono_domain_get();
4406         MonoArray *res;
4407         MonoClass *klass;
4408         int i, j, file_count = 0;
4409         MonoImage **modules;
4410         guint32 module_count, real_module_count;
4411         MonoTableInfo *table;
4412
4413         g_assert (assembly->assembly->image != NULL);
4414
4415         if (assembly->assembly->dynamic) {
4416                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)assembly;
4417
4418                 if (assemblyb->modules)
4419                         module_count = mono_array_length (assemblyb->modules);
4420                 else
4421                         module_count = 0;
4422                 real_module_count = module_count;
4423
4424                 modules = g_new0 (MonoImage*, module_count);
4425                 if (assemblyb->modules) {
4426                         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4427                                 modules [i] = 
4428                                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i)->module.image;
4429                         }
4430                 }
4431         }
4432         else {
4433                 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4434                 file_count = table->rows;
4435
4436                 modules = assembly->assembly->image->modules;
4437                 module_count = assembly->assembly->image->module_count;
4438
4439                 real_module_count = 0;
4440                 for (i = 0; i < module_count; ++i)
4441                         if (modules [i])
4442                                 real_module_count ++;
4443         }
4444
4445         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4446         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4447
4448         mono_array_setref (res, 0, mono_module_get_object (domain, assembly->assembly->image));
4449         j = 1;
4450         for (i = 0; i < module_count; ++i)
4451                 if (modules [i]) {
4452                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4453                         ++j;
4454                 }
4455
4456         for (i = 0; i < file_count; ++i, ++j)
4457                 mono_array_setref (res, j, mono_module_file_get_object (domain, assembly->assembly->image, i));
4458
4459         if (assembly->assembly->dynamic)
4460                 g_free (modules);
4461
4462         return res;
4463 }
4464
4465 static MonoReflectionMethod*
4466 ves_icall_GetCurrentMethod (void) 
4467 {
4468         MonoMethod *m = mono_method_get_last_managed ();
4469
4470         MONO_ARCH_SAVE_REGS;
4471
4472         return mono_method_get_object (mono_domain_get (), m, NULL);
4473 }
4474
4475 static MonoReflectionMethod*
4476 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4477 {
4478         /* FIXME check that method belongs to klass or a parent */
4479         MonoClass *klass;
4480         if (type)
4481                 klass = mono_class_from_mono_type (type);
4482         else
4483                 klass = method->klass;
4484         return mono_method_get_object (mono_domain_get (), method, klass);
4485 }
4486
4487 static MonoReflectionMethod*
4488 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4489 {
4490         return mono_method_get_object (mono_domain_get (), method, NULL);
4491 }
4492
4493 static MonoReflectionMethodBody*
4494 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4495 {
4496         return mono_method_body_get_object (mono_domain_get (), method);
4497 }
4498
4499 static MonoReflectionAssembly*
4500 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4501 {
4502         MonoMethod *m = mono_method_get_last_managed ();
4503
4504         MONO_ARCH_SAVE_REGS;
4505
4506         return mono_assembly_get_object (mono_domain_get (), m->klass->image->assembly);
4507 }
4508
4509
4510 static MonoReflectionAssembly*
4511 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4512 {
4513         MonoDomain* domain = mono_domain_get ();
4514
4515         MONO_ARCH_SAVE_REGS;
4516
4517         if (!domain->entry_assembly)
4518                 return NULL;
4519
4520         return mono_assembly_get_object (domain, domain->entry_assembly);
4521 }
4522
4523 static MonoReflectionAssembly*
4524 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4525 {
4526         MonoMethod *m = mono_method_get_last_managed ();
4527         MonoMethod *dest = m;
4528
4529         MONO_ARCH_SAVE_REGS;
4530
4531         mono_stack_walk_no_il (get_caller, &dest);
4532         if (!dest)
4533                 dest = m;
4534         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4535 }
4536
4537 static MonoString *
4538 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4539                                        gboolean assembly_qualified)
4540 {
4541         MonoDomain *domain = mono_object_domain (object); 
4542         MonoTypeNameFormat format;
4543         MonoString *res;
4544         gchar *name;
4545
4546         MONO_ARCH_SAVE_REGS;
4547         if (full_name)
4548                 format = assembly_qualified ?
4549                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4550                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
4551         else
4552                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4553  
4554         name = mono_type_get_name_full (object->type, format);
4555         if (!name)
4556                 return NULL;
4557
4558         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4559                 g_free (name);
4560                 return NULL;
4561         }
4562
4563         res = mono_string_new (domain, name);
4564         g_free (name);
4565
4566         return res;
4567 }
4568
4569 static void
4570 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version)
4571 {
4572         static MonoMethod *create_culture = NULL;
4573         gpointer args [1];
4574         guint32 pkey_len;
4575         const char *pkey_ptr;
4576         gchar *codebase;
4577
4578         MONO_ARCH_SAVE_REGS;
4579
4580         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4581         aname->major = name->major;
4582         aname->minor = name->minor;
4583         aname->build = name->build;
4584         aname->revision = name->revision;
4585         aname->hashalg = name->hash_alg;
4586         if (by_default_version)
4587                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4588         
4589         codebase = g_filename_to_uri (absolute, NULL, NULL);
4590         if (codebase) {
4591                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4592                 g_free (codebase);
4593         }
4594
4595         if (!create_culture) {
4596                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateSpecificCulture(string)", TRUE);
4597                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4598                 g_assert (create_culture);
4599                 mono_method_desc_free (desc);
4600         }
4601
4602         if (name->culture) {
4603                 args [0] = mono_string_new (domain, name->culture);
4604                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4605         }
4606
4607         if (name->public_key) {
4608                 pkey_ptr = (char*)name->public_key;
4609                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4610
4611                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4612                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4613         }
4614
4615         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4616         if (name->public_key_token [0]) {
4617                 int i, j;
4618                 char *p;
4619
4620                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4621                 p = mono_array_addr (aname->keyToken, char, 0);
4622
4623                 for (i = 0, j = 0; i < 8; i++) {
4624                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4625                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4626                         p++;
4627                 }
4628         }
4629 }
4630
4631 static void
4632 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4633 {
4634         gchar *absolute;
4635         MonoAssembly *mass = assembly->assembly;
4636
4637         MONO_ARCH_SAVE_REGS;
4638
4639         if (g_path_is_absolute (mass->image->name)) {
4640                 fill_reflection_assembly_name (mono_object_domain (assembly),
4641                         aname, &mass->aname, mass->image->name, TRUE);
4642                 return;
4643         }
4644         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4645
4646         fill_reflection_assembly_name (mono_object_domain (assembly),
4647                 aname, &mass->aname, absolute, TRUE);
4648
4649         g_free (absolute);
4650 }
4651
4652 static void
4653 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4654 {
4655         char *filename;
4656         MonoImageOpenStatus status = MONO_IMAGE_OK;
4657         gboolean res;
4658         MonoImage *image;
4659         MonoAssemblyName name;
4660
4661         MONO_ARCH_SAVE_REGS;
4662
4663         filename = mono_string_to_utf8 (fname);
4664
4665         image = mono_image_open (filename, &status);
4666
4667         if (!image){
4668                 MonoException *exc;
4669
4670                 g_free (filename);
4671                 if (status == MONO_IMAGE_IMAGE_INVALID)
4672                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
4673                 else
4674                         exc = mono_get_exception_file_not_found2 (NULL, fname);
4675                 mono_raise_exception (exc);
4676         }
4677
4678         res = mono_assembly_fill_assembly_name (image, &name);
4679         if (!res) {
4680                 mono_image_close (image);
4681                 g_free (filename);
4682                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4683         }
4684
4685         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE);
4686
4687         g_free (filename);
4688         mono_image_close (image);
4689 }
4690
4691 static MonoBoolean
4692 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4693         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4694 {
4695         MonoBoolean result = FALSE;
4696         MonoDeclSecurityEntry entry;
4697
4698         /* SecurityAction.RequestMinimum */
4699         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4700                 *minimum = entry.blob;
4701                 *minLength = entry.size;
4702                 result = TRUE;
4703         }
4704         /* SecurityAction.RequestOptional */
4705         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4706                 *optional = entry.blob;
4707                 *optLength = entry.size;
4708                 result = TRUE;
4709         }
4710         /* SecurityAction.RequestRefuse */
4711         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4712                 *refused = entry.blob;
4713                 *refLength = entry.size;
4714                 result = TRUE;
4715         }
4716
4717         return result;  
4718 }
4719
4720 static MonoArray*
4721 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoBoolean exportedOnly)
4722 {
4723         MonoArray *res;
4724         MonoClass *klass;
4725         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4726         int i, count;
4727         guint32 attrs, visibility;
4728
4729         /* we start the count from 1 because we skip the special type <Module> */
4730         if (exportedOnly) {
4731                 count = 0;
4732                 for (i = 1; i < tdef->rows; ++i) {
4733                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4734                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4735                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
4736                                 count++;
4737                 }
4738         } else {
4739                 count = tdef->rows - 1;
4740         }
4741         res = mono_array_new (domain, mono_defaults.monotype_class, count);
4742         count = 0;
4743         for (i = 1; i < tdef->rows; ++i) {
4744                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4745                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4746                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
4747                         klass = mono_class_get_throw (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
4748                         if (mono_loader_get_last_error ())
4749                                 mono_loader_clear_error ();
4750                         mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4751                         count++;
4752                 }
4753         }
4754         
4755         return res;
4756 }
4757
4758 static MonoArray*
4759 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4760 {
4761         MonoArray *res = NULL;
4762         MonoImage *image = NULL;
4763         MonoTableInfo *table = NULL;
4764         MonoDomain *domain;
4765         GList *list = NULL;
4766         int i, len;
4767
4768         MONO_ARCH_SAVE_REGS;
4769
4770         domain = mono_object_domain (assembly);
4771
4772         if (assembly->assembly->dynamic) {
4773                 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4774                 if (abuilder->modules) {
4775                         for (i = 0; i < mono_array_length(abuilder->modules); i++) {
4776                                 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4777                                 MonoArray *append = mb->types;
4778                                 /* The types array might not be fully filled up */
4779                                 if (append && mb->num_types > 0) {
4780                                         guint32 len1, len2;
4781                                         MonoArray *new;
4782                                         len1 = res ? mono_array_length (res) : 0;
4783                                         len2 = mb->num_types;
4784                                         new = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4785                                         if (res)
4786                                                 mono_array_memcpy_refs (new, 0, res, 0, len1);
4787                                         mono_array_memcpy_refs (new, len1, append, 0, len2);
4788                                         res = new;
4789                                 }
4790                         }
4791
4792                         /*
4793                          * Replace TypeBuilders with the created types to be compatible
4794                          * with MS.NET.
4795                          */
4796                         if (res) {
4797                                 for (i = 0; i < mono_array_length (res); ++i) {
4798                                         MonoReflectionTypeBuilder *tb = mono_array_get (res, MonoReflectionTypeBuilder*, i);
4799                                         if (tb->created)
4800                                                 mono_array_setref (res, i, tb->created);
4801                                 }
4802                         }
4803                 }
4804
4805                 if (abuilder->loaded_modules)
4806                         for (i = 0; i < mono_array_length(abuilder->loaded_modules); i++) {
4807                                 MonoReflectionModule *rm = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4808                                 MonoArray *append = mono_module_get_types (domain, rm->image, exportedOnly);
4809                                 if (append && mono_array_length (append) > 0) {
4810                                         guint32 len1, len2;
4811                                         MonoArray *new;
4812                                         len1 = res ? mono_array_length (res) : 0;
4813                                         len2 = mono_array_length (append);
4814                                         new = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4815                                         if (res)
4816                                                 mono_array_memcpy_refs (new, 0, res, 0, len1);
4817                                         mono_array_memcpy_refs (new, len1, append, 0, len2);
4818                                         res = new;
4819                                 }
4820                         }
4821                 if (res)
4822                         return res;
4823                 else
4824                         return mono_array_new (domain, mono_defaults.monotype_class, 0);
4825         }
4826         image = assembly->assembly->image;
4827         table = &image->tables [MONO_TABLE_FILE];
4828         res = mono_module_get_types (domain, image, exportedOnly);
4829
4830         /* Append data from all modules in the assembly */
4831         for (i = 0; i < table->rows; ++i) {
4832                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4833                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
4834                         if (loaded_image) {
4835                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, exportedOnly);
4836                                 /* Append the new types to the end of the array */
4837                                 if (mono_array_length (res2) > 0) {
4838                                         guint32 len1, len2;
4839                                         MonoArray *res3;
4840
4841                                         len1 = mono_array_length (res);
4842                                         len2 = mono_array_length (res2);
4843                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4844                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
4845                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
4846                                         res = res3;
4847                                 }
4848                         }
4849                 }
4850         }
4851
4852         /* the ReflectionTypeLoadException must have all the types (Types property), 
4853          * NULL replacing types which throws an exception. The LoaderException must
4854          * contain all exceptions for NULL items.
4855          */
4856
4857         len = mono_array_length (res);
4858
4859         for (i = 0; i < len; i++) {
4860                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
4861                 MonoClass *klass = mono_type_get_class (t->type);
4862                 if ((klass != NULL) && klass->exception_type) {
4863                         /* keep the class in the list */
4864                         list = g_list_append (list, klass);
4865                         /* and replace Type with NULL */
4866                         mono_array_setref (res, i, NULL);
4867                 }
4868         }
4869
4870         if (list) {
4871                 GList *tmp = NULL;
4872                 MonoException *exc = NULL;
4873                 MonoArray *exl = NULL;
4874                 int length = g_list_length (list);
4875
4876                 mono_loader_clear_error ();
4877
4878                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
4879                 for (i = 0, tmp = list; i < length; i++, tmp = tmp->next) {
4880                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
4881                         mono_array_setref (exl, i, exc);
4882                 }
4883                 g_list_free (list);
4884                 list = NULL;
4885
4886                 exc = mono_get_exception_reflection_type_load (res, exl);
4887                 mono_loader_clear_error ();
4888                 mono_raise_exception (exc);
4889         }
4890                 
4891         return res;
4892 }
4893
4894 static gboolean
4895 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
4896 {
4897         MonoAssemblyName aname;
4898         MonoDomain *domain = mono_object_domain (name);
4899         char *val;
4900         gboolean is_version_defined;
4901
4902         val = mono_string_to_utf8 (assname);
4903         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined))
4904                 return FALSE;
4905         
4906         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined);
4907
4908         mono_assembly_name_free (&aname);
4909         g_free ((guint8*) aname.public_key);
4910         g_free (val);
4911
4912         return TRUE;
4913 }
4914
4915 static MonoReflectionType*
4916 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
4917 {
4918         MonoDomain *domain = mono_object_domain (module); 
4919         MonoClass *klass;
4920
4921         MONO_ARCH_SAVE_REGS;
4922
4923         g_assert (module->image);
4924
4925         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
4926                 /* These images do not have a global type */
4927                 return NULL;
4928
4929         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
4930         return mono_type_get_object (domain, &klass->byval_arg);
4931 }
4932
4933 static void
4934 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
4935 {
4936         /*if (module->image)
4937                 mono_image_close (module->image);*/
4938 }
4939
4940 static MonoString*
4941 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
4942 {
4943         MonoDomain *domain = mono_object_domain (module); 
4944
4945         MONO_ARCH_SAVE_REGS;
4946
4947         g_assert (module->image);
4948         return mono_string_new (domain, module->image->guid);
4949 }
4950
4951 static void
4952 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
4953 {
4954         if (image->dynamic) {
4955                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
4956                 *pe_kind = dyn->pe_kind;
4957                 *machine = dyn->machine;
4958         }
4959         else {
4960                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
4961                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
4962         }
4963 }
4964
4965 static gint32
4966 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
4967 {
4968         return (image->md_version_major << 16) | (image->md_version_minor);
4969 }
4970
4971 static MonoArray*
4972 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
4973 {
4974         MONO_ARCH_SAVE_REGS;
4975
4976         if (!module->image)
4977                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
4978         else
4979                 return mono_module_get_types (mono_object_domain (module), module->image, FALSE);
4980 }
4981
4982 static gboolean
4983 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
4984 {
4985         guint32 cols [MONO_MEMBERREF_SIZE];
4986         const char *sig;
4987         mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4988         sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4989         mono_metadata_decode_blob_size (sig, &sig);
4990         return (*sig != 0x6);
4991 }
4992
4993 static void
4994 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
4995 {
4996         if (type_args)
4997                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
4998                                                                       mono_array_addr (type_args, MonoType*, 0));
4999         else
5000                 context->class_inst = NULL;
5001         if (method_args)
5002                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5003                                                                        mono_array_addr (method_args, MonoType*, 0));
5004         else
5005                 context->method_inst = NULL;
5006 }
5007
5008 static MonoType*
5009 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5010 {
5011         MonoClass *klass;
5012         int table = mono_metadata_token_table (token);
5013         int index = mono_metadata_token_index (token);
5014         MonoGenericContext context;
5015
5016         *error = ResolveTokenError_Other;
5017
5018         /* Validate token */
5019         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5020                 (table != MONO_TABLE_TYPESPEC)) {
5021                 *error = ResolveTokenError_BadTable;
5022                 return NULL;
5023         }
5024
5025         if (image->dynamic) {
5026                 if (type_args || method_args)
5027                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5028                 return mono_lookup_dynamic_token (image, token, NULL);
5029         }
5030
5031         if ((index <= 0) || (index > image->tables [table].rows)) {
5032                 *error = ResolveTokenError_OutOfRange;
5033                 return NULL;
5034         }
5035
5036         init_generic_context_from_args (&context, type_args, method_args);
5037         klass = mono_class_get_full (image, token, &context);
5038
5039         if (klass)
5040                 return &klass->byval_arg;
5041         else
5042                 return NULL;
5043 }
5044
5045 static MonoMethod*
5046 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5047 {
5048         int table = mono_metadata_token_table (token);
5049         int index = mono_metadata_token_index (token);
5050         MonoGenericContext context;
5051         MonoMethod *method;
5052
5053         *error = ResolveTokenError_Other;
5054
5055         /* Validate token */
5056         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5057                 (table != MONO_TABLE_MEMBERREF)) {
5058                 *error = ResolveTokenError_BadTable;
5059                 return NULL;
5060         }
5061
5062         if (image->dynamic) {
5063                 if (type_args || method_args)
5064                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5065                 /* FIXME: validate memberref token type */
5066                 return mono_lookup_dynamic_token (image, token, NULL);
5067         }
5068
5069         if ((index <= 0) || (index > image->tables [table].rows)) {
5070                 *error = ResolveTokenError_OutOfRange;
5071                 return NULL;
5072         }
5073         if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5074                 *error = ResolveTokenError_BadTable;
5075                 return NULL;
5076         }
5077
5078         init_generic_context_from_args (&context, type_args, method_args);
5079         method = mono_get_method_full (image, token, NULL, &context);
5080
5081         return method;
5082 }
5083
5084 static MonoString*
5085 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5086 {
5087         int index = mono_metadata_token_index (token);
5088
5089         *error = ResolveTokenError_Other;
5090
5091         /* Validate token */
5092         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5093                 *error = ResolveTokenError_BadTable;
5094                 return NULL;
5095         }
5096
5097         if (image->dynamic)
5098                 return mono_lookup_dynamic_token (image, token, NULL);
5099
5100         if ((index <= 0) || (index >= image->heap_us.size)) {
5101                 *error = ResolveTokenError_OutOfRange;
5102                 return NULL;
5103         }
5104
5105         /* FIXME: What to do if the index points into the middle of a string ? */
5106
5107         return mono_ldstr (mono_domain_get (), image, index);
5108 }
5109
5110 static MonoClassField*
5111 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5112 {
5113         MonoClass *klass;
5114         int table = mono_metadata_token_table (token);
5115         int index = mono_metadata_token_index (token);
5116         MonoGenericContext context;
5117         MonoClassField *field;
5118
5119         *error = ResolveTokenError_Other;
5120
5121         /* Validate token */
5122         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5123                 *error = ResolveTokenError_BadTable;
5124                 return NULL;
5125         }
5126
5127         if (image->dynamic) {
5128                 if (type_args || method_args)
5129                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5130                 /* FIXME: validate memberref token type */
5131                 return mono_lookup_dynamic_token (image, token, NULL);
5132         }
5133
5134         if ((index <= 0) || (index > image->tables [table].rows)) {
5135                 *error = ResolveTokenError_OutOfRange;
5136                 return NULL;
5137         }
5138         if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5139                 *error = ResolveTokenError_BadTable;
5140                 return NULL;
5141         }
5142
5143         init_generic_context_from_args (&context, type_args, method_args);
5144         field = mono_field_from_token (image, token, &klass, &context);
5145         
5146         return field;
5147 }
5148
5149
5150 static MonoObject*
5151 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5152 {
5153         int table = mono_metadata_token_table (token);
5154
5155         *error = ResolveTokenError_Other;
5156
5157         switch (table) {
5158         case MONO_TABLE_TYPEDEF:
5159         case MONO_TABLE_TYPEREF:
5160         case MONO_TABLE_TYPESPEC: {
5161                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5162                 if (t)
5163                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5164                 else
5165                         return NULL;
5166         }
5167         case MONO_TABLE_METHOD:
5168         case MONO_TABLE_METHODSPEC: {
5169                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5170                 if (m)
5171                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5172                 else
5173                         return NULL;
5174         }               
5175         case MONO_TABLE_FIELD: {
5176                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5177                 if (f)
5178                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5179                 else
5180                         return NULL;
5181         }
5182         case MONO_TABLE_MEMBERREF:
5183                 if (mono_metadata_memberref_is_method (image, token)) {
5184                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5185                         if (m)
5186                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5187                         else
5188                                 return NULL;
5189                 }
5190                 else {
5191                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5192                         if (f)
5193                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5194                         else
5195                                 return NULL;
5196                 }
5197                 break;
5198
5199         default:
5200                 *error = ResolveTokenError_BadTable;
5201         }
5202
5203         return NULL;
5204 }
5205
5206 static MonoArray*
5207 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5208 {
5209         int table = mono_metadata_token_table (token);
5210         int idx = mono_metadata_token_index (token);
5211         MonoTableInfo *tables = image->tables;
5212         guint32 sig, len;
5213         const char *ptr;
5214         MonoArray *res;
5215
5216         *error = ResolveTokenError_OutOfRange;
5217
5218         /* FIXME: Support other tables ? */
5219         if (table != MONO_TABLE_STANDALONESIG)
5220                 return NULL;
5221
5222         if (image->dynamic)
5223                 return NULL;
5224
5225         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5226                 return NULL;
5227
5228         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5229
5230         ptr = mono_metadata_blob_heap (image, sig);
5231         len = mono_metadata_decode_blob_size (ptr, &ptr);
5232
5233         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5234         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5235         return res;
5236 }
5237
5238 static MonoReflectionType*
5239 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5240 {
5241         MonoClass *klass;
5242         int isbyref = 0, rank;
5243         char *str = mono_string_to_utf8 (smodifiers);
5244         char *p;
5245
5246         MONO_ARCH_SAVE_REGS;
5247
5248         klass = mono_class_from_mono_type (tb->type.type);
5249         p = str;
5250         /* logic taken from mono_reflection_parse_type(): keep in sync */
5251         while (*p) {
5252                 switch (*p) {
5253                 case '&':
5254                         if (isbyref) { /* only one level allowed by the spec */
5255                                 g_free (str);
5256                                 return NULL;
5257                         }
5258                         isbyref = 1;
5259                         p++;
5260                         g_free (str);
5261                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5262                         break;
5263                 case '*':
5264                         klass = mono_ptr_class_get (&klass->byval_arg);
5265                         mono_class_init (klass);
5266                         p++;
5267                         break;
5268                 case '[':
5269                         rank = 1;
5270                         p++;
5271                         while (*p) {
5272                                 if (*p == ']')
5273                                         break;
5274                                 if (*p == ',')
5275                                         rank++;
5276                                 else if (*p != '*') { /* '*' means unknown lower bound */
5277                                         g_free (str);
5278                                         return NULL;
5279                                 }
5280                                 ++p;
5281                         }
5282                         if (*p != ']') {
5283                                 g_free (str);
5284                                 return NULL;
5285                         }
5286                         p++;
5287                         klass = mono_array_class_get (klass, rank);
5288                         mono_class_init (klass);
5289                         break;
5290                 default:
5291                         break;
5292                 }
5293         }
5294         g_free (str);
5295         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5296 }
5297
5298 static MonoBoolean
5299 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5300 {
5301         MonoType *type;
5302         MonoBoolean res;
5303
5304         MONO_ARCH_SAVE_REGS;
5305
5306         type = t->type;
5307         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5308
5309         return res;
5310 }
5311
5312 static MonoReflectionType *
5313 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5314 {
5315         MonoClass *klass, *aklass;
5316
5317         MONO_ARCH_SAVE_REGS;
5318
5319         klass = mono_class_from_mono_type (type->type);
5320         aklass = mono_array_class_get (klass, rank);
5321
5322         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5323 }
5324
5325 static MonoReflectionType *
5326 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5327 {
5328         MonoClass *klass;
5329
5330         MONO_ARCH_SAVE_REGS;
5331
5332         klass = mono_class_from_mono_type (type->type);
5333
5334         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5335 }
5336
5337 static MonoReflectionType *
5338 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5339 {
5340         MonoClass *pklass;
5341
5342         MONO_ARCH_SAVE_REGS;
5343
5344         pklass = mono_ptr_class_get (type->type);
5345
5346         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5347 }
5348
5349 static MonoObject *
5350 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5351                                                    MonoReflectionMethod *info)
5352 {
5353         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5354         MonoObject *delegate;
5355         gpointer func;
5356
5357         MONO_ARCH_SAVE_REGS;
5358
5359         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5360
5361         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5362
5363         func = mono_compile_method (info->method);
5364
5365         mono_delegate_ctor (delegate, target, func);
5366
5367         return delegate;
5368 }
5369
5370 static void
5371 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5372 {
5373         gpointer iter;
5374         MonoMethod *invoke;
5375
5376         /* Find the Invoke method */
5377         iter = NULL;
5378         while ((invoke = mono_class_get_methods (this->object.vtable->klass, &iter))) {
5379                 if (!strcmp (invoke->name, "Invoke"))
5380                         break;
5381         }
5382         g_assert (invoke);
5383
5384         this->invoke_impl = mono_compile_method (mono_marshal_get_delegate_invoke (invoke));
5385 }
5386
5387 /*
5388  * Magic number to convert a time which is relative to
5389  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5390  */
5391 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5392
5393 /*
5394  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5395  */
5396 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5397
5398 /*
5399  * This returns Now in UTC
5400  */
5401 static gint64
5402 ves_icall_System_DateTime_GetNow (void)
5403 {
5404 #ifdef PLATFORM_WIN32
5405         SYSTEMTIME st;
5406         FILETIME ft;
5407         
5408         GetSystemTime (&st);
5409         SystemTimeToFileTime (&st, &ft);
5410         return (gint64) FILETIME_ADJUST + ((((gint64)ft.dwHighDateTime)<<32) | ft.dwLowDateTime);
5411 #else
5412         /* FIXME: put this in io-layer and call it GetLocalTime */
5413         struct timeval tv;
5414         gint64 res;
5415
5416         MONO_ARCH_SAVE_REGS;
5417
5418         if (gettimeofday (&tv, NULL) == 0) {
5419                 res = (((gint64)tv.tv_sec + EPOCH_ADJUST)* 1000000 + tv.tv_usec)*10;
5420                 return res;
5421         }
5422         /* fixme: raise exception */
5423         return 0;
5424 #endif
5425 }
5426
5427 #ifdef PLATFORM_WIN32
5428 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5429 static void
5430 convert_to_absolute_date(SYSTEMTIME *date)
5431 {
5432 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5433         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5434         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5435         /* from the calendar FAQ */
5436         int a = (14 - date->wMonth) / 12;
5437         int y = date->wYear - a;
5438         int m = date->wMonth + 12 * a - 2;
5439         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5440
5441         /* d is now the day of the week for the first of the month (0 == Sunday) */
5442
5443         int day_of_week = date->wDayOfWeek;
5444
5445         /* set day_in_month to the first day in the month which falls on day_of_week */    
5446         int day_in_month = 1 + (day_of_week - d);
5447         if (day_in_month <= 0)
5448                 day_in_month += 7;
5449
5450         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5451         date->wDay = day_in_month + (date->wDay - 1) * 7;
5452         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5453                 date->wDay -= 7;
5454 }
5455 #endif
5456
5457 #ifndef PLATFORM_WIN32
5458 /*
5459  * Return's the offset from GMT of a local time.
5460  * 
5461  *  tm is a local time
5462  *  t  is the same local time as seconds.
5463  */
5464 static int 
5465 gmt_offset(struct tm *tm, time_t t)
5466 {
5467 #if defined (HAVE_TM_GMTOFF)
5468         return tm->tm_gmtoff;
5469 #else
5470         struct tm g;
5471         time_t t2;
5472         g = *gmtime(&t);
5473         g.tm_isdst = tm->tm_isdst;
5474         t2 = mktime(&g);
5475         return (int)difftime(t, t2);
5476 #endif
5477 }
5478 #endif
5479 /*
5480  * This is heavily based on zdump.c from glibc 2.2.
5481  *
5482  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5483  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5484  *  * data[2]:  utcoffset (in TimeSpan ticks).
5485  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5486  *  * name[0]:  name of this timezone when not daylight saving.
5487  *  * name[1]:  name of this timezone when daylight saving.
5488  *
5489  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5490  *         the class library allows years between 1 and 9999.
5491  *
5492  *  Returns true on success and zero on failure.
5493  */
5494 static guint32
5495 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5496 {
5497 #ifndef PLATFORM_WIN32
5498         MonoDomain *domain = mono_domain_get ();
5499         struct tm start, tt;
5500         time_t t;
5501
5502         long int gmtoff;
5503         int is_daylight = 0, day;
5504         char tzone [64];
5505
5506         MONO_ARCH_SAVE_REGS;
5507
5508         MONO_CHECK_ARG_NULL (data);
5509         MONO_CHECK_ARG_NULL (names);
5510
5511         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5512         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5513
5514         /* 
5515          * no info is better than crashing: we'll need our own tz data
5516          * to make this work properly, anyway. The range is probably
5517          * reduced to 1970 .. 2037 because that is what mktime is
5518          * guaranteed to support (we get into an infinite loop
5519          * otherwise).
5520          */
5521
5522         memset (&start, 0, sizeof (start));
5523
5524         start.tm_mday = 1;
5525         start.tm_year = year-1900;
5526
5527         t = mktime (&start);
5528
5529         if ((year < 1970) || (year > 2037) || (t == -1)) {
5530                 t = time (NULL);
5531                 tt = *localtime (&t);
5532                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5533                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5534                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5535                 return 1;
5536         }
5537
5538         gmtoff = gmt_offset (&start, t);
5539
5540         /* For each day of the year, calculate the tm_gmtoff. */
5541         for (day = 0; day < 365; day++) {
5542
5543                 t += 3600*24;
5544                 tt = *localtime (&t);
5545
5546                 /* Daylight saving starts or ends here. */
5547                 if (gmt_offset (&tt, t) != gmtoff) {
5548                         struct tm tt1;
5549                         time_t t1;
5550
5551                         /* Try to find the exact hour when daylight saving starts/ends. */
5552                         t1 = t;
5553                         do {
5554                                 t1 -= 3600;
5555                                 tt1 = *localtime (&t1);
5556                         } while (gmt_offset (&tt1, t1) != gmtoff);
5557
5558                         /* Try to find the exact minute when daylight saving starts/ends. */
5559                         do {
5560                                 t1 += 60;
5561                                 tt1 = *localtime (&t1);
5562                         } while (gmt_offset (&tt1, t1) == gmtoff);
5563                         t1+=gmtoff;
5564                         strftime (tzone, sizeof (tzone), "%Z", &tt);
5565                         
5566                         /* Write data, if we're already in daylight saving, we're done. */
5567                         if (is_daylight) {
5568                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5569                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5570                                 return 1;
5571                         } else {
5572                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5573                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5574                                 is_daylight = 1;
5575                         }
5576
5577                         /* This is only set once when we enter daylight saving. */
5578                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5579                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5580
5581                         gmtoff = gmt_offset (&tt, t);
5582                 }
5583         }
5584
5585         if (!is_daylight) {
5586                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5587                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5588                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5589                 mono_array_set ((*data), gint64, 0, 0);
5590                 mono_array_set ((*data), gint64, 1, 0);
5591                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5592                 mono_array_set ((*data), gint64, 3, 0);
5593         }
5594
5595         return 1;
5596 #else
5597         MonoDomain *domain = mono_domain_get ();
5598         TIME_ZONE_INFORMATION tz_info;
5599         FILETIME ft;
5600         int i;
5601         int err, tz_id;
5602
5603         tz_id = GetTimeZoneInformation (&tz_info);
5604         if (tz_id == TIME_ZONE_ID_INVALID)
5605                 return 0;
5606
5607         MONO_CHECK_ARG_NULL (data);
5608         MONO_CHECK_ARG_NULL (names);
5609
5610         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5611         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5612
5613         for (i = 0; i < 32; ++i)
5614                 if (!tz_info.DaylightName [i])
5615                         break;
5616         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5617         for (i = 0; i < 32; ++i)
5618                 if (!tz_info.StandardName [i])
5619                         break;
5620         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5621
5622         if ((year <= 1601) || (year > 30827)) {
5623                 /*
5624                  * According to MSDN, the MS time functions can't handle dates outside
5625                  * this interval.
5626                  */
5627                 return 1;
5628         }
5629
5630         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5631         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5632                 tz_info.StandardDate.wYear = year;
5633                 convert_to_absolute_date(&tz_info.StandardDate);
5634                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5635                 g_assert(err);
5636                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5637                 tz_info.DaylightDate.wYear = year;
5638                 convert_to_absolute_date(&tz_info.DaylightDate);
5639                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5640                 g_assert(err);
5641                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5642         }
5643         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5644         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
5645
5646         return 1;
5647 #endif
5648 }
5649
5650 static gpointer
5651 ves_icall_System_Object_obj_address (MonoObject *this) 
5652 {
5653         MONO_ARCH_SAVE_REGS;
5654
5655         return this;
5656 }
5657
5658 /* System.Buffer */
5659
5660 static inline gint32 
5661 mono_array_get_byte_length (MonoArray *array)
5662 {
5663         MonoClass *klass;
5664         int length;
5665         int i;
5666
5667         klass = array->obj.vtable->klass;
5668
5669         if (array->bounds == NULL)
5670                 length = array->max_length;
5671         else {
5672                 length = 1;
5673                 for (i = 0; i < klass->rank; ++ i)
5674                         length *= array->bounds [i].length;
5675         }
5676
5677         switch (klass->element_class->byval_arg.type) {
5678         case MONO_TYPE_I1:
5679         case MONO_TYPE_U1:
5680         case MONO_TYPE_BOOLEAN:
5681                 return length;
5682         case MONO_TYPE_I2:
5683         case MONO_TYPE_U2:
5684         case MONO_TYPE_CHAR:
5685                 return length << 1;
5686         case MONO_TYPE_I4:
5687         case MONO_TYPE_U4:
5688         case MONO_TYPE_R4:
5689                 return length << 2;
5690         case MONO_TYPE_I:
5691         case MONO_TYPE_U:
5692                 return length * sizeof (gpointer);
5693         case MONO_TYPE_I8:
5694         case MONO_TYPE_U8:
5695         case MONO_TYPE_R8:
5696                 return length << 3;
5697         default:
5698                 return -1;
5699         }
5700 }
5701
5702 static gint32 
5703 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
5704 {
5705         MONO_ARCH_SAVE_REGS;
5706
5707         return mono_array_get_byte_length (array);
5708 }
5709
5710 static gint8 
5711 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
5712 {
5713         MONO_ARCH_SAVE_REGS;
5714
5715         return mono_array_get (array, gint8, idx);
5716 }
5717
5718 static void 
5719 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
5720 {
5721         MONO_ARCH_SAVE_REGS;
5722
5723         mono_array_set (array, gint8, idx, value);
5724 }
5725
5726 static MonoBoolean
5727 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
5728 {
5729         guint8 *src_buf, *dest_buf;
5730
5731         MONO_ARCH_SAVE_REGS;
5732
5733         /* watch out for integer overflow */
5734         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5735                 return FALSE;
5736
5737         src_buf = (guint8 *)src->vector + src_offset;
5738         dest_buf = (guint8 *)dest->vector + dest_offset;
5739
5740         if (src != dest)
5741                 memcpy (dest_buf, src_buf, count);
5742         else
5743                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5744
5745         return TRUE;
5746 }
5747
5748 static MonoObject *
5749 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
5750 {
5751         MonoDomain *domain = mono_object_domain (this); 
5752         MonoObject *res;
5753         MonoRealProxy *rp = ((MonoRealProxy *)this);
5754         MonoTransparentProxy *tp;
5755         MonoType *type;
5756         MonoClass *klass;
5757
5758         MONO_ARCH_SAVE_REGS;
5759
5760         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5761         tp = (MonoTransparentProxy*) res;
5762         
5763         MONO_OBJECT_SETREF (tp, rp, rp);
5764         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5765         klass = mono_class_from_mono_type (type);
5766
5767         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
5768         tp->remote_class = mono_remote_class (domain, class_name, klass);
5769
5770         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
5771         return res;
5772 }
5773
5774 static MonoReflectionType *
5775 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5776 {
5777         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5778 }
5779
5780 /* System.Environment */
5781
5782 static MonoString *
5783 ves_icall_System_Environment_get_MachineName (void)
5784 {
5785 #if defined (PLATFORM_WIN32)
5786         gunichar2 *buf;
5787         guint32 len;
5788         MonoString *result;
5789
5790         len = MAX_COMPUTERNAME_LENGTH + 1;
5791         buf = g_new (gunichar2, len);
5792
5793         result = NULL;
5794         if (GetComputerName (buf, (PDWORD) &len))
5795                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5796
5797         g_free (buf);
5798         return result;
5799 #else
5800         gchar buf [256];
5801         MonoString *result;
5802
5803         if (gethostname (buf, sizeof (buf)) == 0)
5804                 result = mono_string_new (mono_domain_get (), buf);
5805         else
5806                 result = NULL;
5807         
5808         return result;
5809 #endif
5810 }
5811
5812 static int
5813 ves_icall_System_Environment_get_Platform (void)
5814 {
5815         MONO_ARCH_SAVE_REGS;
5816
5817 #if defined (PLATFORM_WIN32)
5818         /* Win32NT */
5819         return 2;
5820 #else
5821         /* Unix */
5822         return 128;
5823 #endif
5824 }
5825
5826 static MonoString *
5827 ves_icall_System_Environment_get_NewLine (void)
5828 {
5829         MONO_ARCH_SAVE_REGS;
5830
5831 #if defined (PLATFORM_WIN32)
5832         return mono_string_new (mono_domain_get (), "\r\n");
5833 #else
5834         return mono_string_new (mono_domain_get (), "\n");
5835 #endif
5836 }
5837
5838 static MonoString *
5839 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5840 {
5841         const gchar *value;
5842         gchar *utf8_name;
5843
5844         MONO_ARCH_SAVE_REGS;
5845
5846         if (name == NULL)
5847                 return NULL;
5848
5849         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5850         value = g_getenv (utf8_name);
5851
5852         g_free (utf8_name);
5853
5854         if (value == 0)
5855                 return NULL;
5856         
5857         return mono_string_new (mono_domain_get (), value);
5858 }
5859
5860 /*
5861  * There is no standard way to get at environ.
5862  */
5863 #ifndef _MSC_VER
5864 #ifndef __MINGW32_VERSION
5865 extern
5866 char **environ;
5867 #endif
5868 #endif
5869
5870 static MonoArray *
5871 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5872 {
5873         MonoArray *names;
5874         MonoDomain *domain;
5875         MonoString *str;
5876         gchar **e, **parts;
5877         int n;
5878
5879         MONO_ARCH_SAVE_REGS;
5880
5881         n = 0;
5882         for (e = environ; *e != 0; ++ e)
5883                 ++ n;
5884
5885         domain = mono_domain_get ();
5886         names = mono_array_new (domain, mono_defaults.string_class, n);
5887
5888         n = 0;
5889         for (e = environ; *e != 0; ++ e) {
5890                 parts = g_strsplit (*e, "=", 2);
5891                 if (*parts != 0) {
5892                         str = mono_string_new (domain, *parts);
5893                         mono_array_setref (names, n, str);
5894                 }
5895
5896                 g_strfreev (parts);
5897
5898                 ++ n;
5899         }
5900
5901         return names;
5902 }
5903
5904 /*
5905  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
5906  */
5907 #if !GLIB_CHECK_VERSION(2,4,0)
5908 #define g_setenv(a,b,c)   setenv(a,b,c)
5909 #define g_unsetenv(a) unsetenv(a)
5910 #endif
5911
5912 static void
5913 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
5914 {
5915 #ifdef PLATFORM_WIN32
5916         gunichar2 *utf16_name, *utf16_value;
5917 #else
5918         gchar *utf8_name, *utf8_value;
5919 #endif
5920
5921         MONO_ARCH_SAVE_REGS;
5922         
5923 #ifdef PLATFORM_WIN32
5924         utf16_name = mono_string_to_utf16 (name);
5925         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
5926                 SetEnvironmentVariable (utf16_name, NULL);
5927                 g_free (utf16_name);
5928                 return;
5929         }
5930
5931         utf16_value = mono_string_to_utf16 (value);
5932
5933         SetEnvironmentVariable (utf16_name, utf16_value);
5934
5935         g_free (utf16_name);
5936         g_free (utf16_value);
5937 #else
5938         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5939
5940         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
5941                 g_unsetenv (utf8_name);
5942                 g_free (utf8_name);
5943                 return;
5944         }
5945
5946         utf8_value = mono_string_to_utf8 (value);
5947         g_setenv (utf8_name, utf8_value, TRUE);
5948
5949         g_free (utf8_name);
5950         g_free (utf8_value);
5951 #endif
5952 }
5953
5954 /*
5955  * Returns: the number of milliseconds elapsed since the system started.
5956  */
5957 static gint32
5958 ves_icall_System_Environment_get_TickCount (void)
5959 {
5960         return GetTickCount ();
5961 }
5962
5963
5964 static void
5965 ves_icall_System_Environment_Exit (int result)
5966 {
5967         MONO_ARCH_SAVE_REGS;
5968
5969         mono_runtime_set_shutting_down ();
5970
5971         /* Suspend all managed threads since the runtime is going away */
5972         mono_thread_suspend_all_other_threads ();
5973
5974         mono_runtime_quit ();
5975
5976         /* we may need to do some cleanup here... */
5977         exit (result);
5978 }
5979
5980 static MonoString*
5981 ves_icall_System_Environment_GetGacPath (void)
5982 {
5983         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
5984 }
5985
5986 static MonoString*
5987 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
5988 {
5989 #if defined (PLATFORM_WIN32)
5990         #ifndef CSIDL_FLAG_CREATE
5991                 #define CSIDL_FLAG_CREATE       0x8000
5992         #endif
5993
5994         WCHAR path [MAX_PATH];
5995         /* Create directory if no existing */
5996         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
5997                 int len = 0;
5998                 while (path [len])
5999                         ++ len;
6000                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6001         }
6002 #else
6003         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6004 #endif
6005         return mono_string_new (mono_domain_get (), "");
6006 }
6007
6008 static MonoArray *
6009 ves_icall_System_Environment_GetLogicalDrives (void)
6010 {
6011         gunichar2 buf [128], *ptr, *dname;
6012         gunichar2 *u16;
6013         gint initial_size = 127, size = 128;
6014         gint ndrives;
6015         MonoArray *result;
6016         MonoString *drivestr;
6017         MonoDomain *domain = mono_domain_get ();
6018         gint len;
6019
6020         MONO_ARCH_SAVE_REGS;
6021
6022         buf [0] = '\0';
6023         ptr = buf;
6024
6025         while (size > initial_size) {
6026                 size = GetLogicalDriveStrings (initial_size, ptr);
6027                 if (size > initial_size) {
6028                         if (ptr != buf)
6029                                 g_free (ptr);
6030                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6031                         initial_size = size;
6032                         size++;
6033                 }
6034         }
6035
6036         /* Count strings */
6037         dname = ptr;
6038         ndrives = 0;
6039         do {
6040                 while (*dname++);
6041                 ndrives++;
6042         } while (*dname);
6043
6044         dname = ptr;
6045         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6046         ndrives = 0;
6047         do {
6048                 len = 0;
6049                 u16 = dname;
6050                 while (*u16) { u16++; len ++; }
6051                 drivestr = mono_string_new_utf16 (domain, dname, len);
6052                 mono_array_setref (result, ndrives++, drivestr);
6053                 while (*dname++);
6054         } while (*dname);
6055
6056         if (ptr != buf)
6057                 g_free (ptr);
6058
6059         return result;
6060 }
6061
6062 static MonoString *
6063 ves_icall_System_Environment_InternalGetHome (void)
6064 {
6065         MONO_ARCH_SAVE_REGS;
6066
6067         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6068 }
6069
6070 static const char *encodings [] = {
6071         (char *) 1,
6072                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6073                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6074                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6075         (char *) 2,
6076                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6077                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6078                 "x_unicode_2_0_utf_7",
6079         (char *) 3,
6080                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6081                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6082         (char *) 4,
6083                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6084                 "iso_10646_ucs2",
6085         (char *) 5,
6086                 "unicodefffe", "utf_16be",
6087         (char *) 6,
6088                 "iso_8859_1",
6089         (char *) 0
6090 };
6091
6092 /*
6093  * Returns the internal codepage, if the value of "int_code_page" is
6094  * 1 at entry, and we can not compute a suitable code page number,
6095  * returns the code page as a string
6096  */
6097 static MonoString*
6098 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6099 {
6100         const char *cset;
6101         const char *p;
6102         char *c;
6103         char *codepage = NULL;
6104         int code;
6105         int want_name = *int_code_page;
6106         int i;
6107         
6108         *int_code_page = -1;
6109         MONO_ARCH_SAVE_REGS;
6110
6111         g_get_charset (&cset);
6112         c = codepage = strdup (cset);
6113         for (c = codepage; *c; c++){
6114                 if (isascii (*c) && isalpha (*c))
6115                         *c = tolower (*c);
6116                 if (*c == '-')
6117                         *c = '_';
6118         }
6119         /* g_print ("charset: %s\n", cset); */
6120         
6121         /* handle some common aliases */
6122         p = encodings [0];
6123         code = 0;
6124         for (i = 0; p != 0; ){
6125                 if ((gssize) p < 7){
6126                         code = (gssize) p;
6127                         p = encodings [++i];
6128                         continue;
6129                 }
6130                 if (strcmp (p, codepage) == 0){
6131                         *int_code_page = code;
6132                         break;
6133                 }
6134                 p = encodings [++i];
6135         }
6136         
6137         if (strstr (codepage, "utf_8") != NULL)
6138                 *int_code_page |= 0x10000000;
6139         free (codepage);
6140         
6141         if (want_name && *int_code_page == -1)
6142                 return mono_string_new (mono_domain_get (), cset);
6143         else
6144                 return NULL;
6145 }
6146
6147 static MonoBoolean
6148 ves_icall_System_Environment_get_HasShutdownStarted (void)
6149 {
6150         if (mono_runtime_is_shutting_down ())
6151                 return TRUE;
6152
6153         if (mono_domain_is_unloading (mono_domain_get ()))
6154                 return TRUE;
6155
6156         return FALSE;
6157 }
6158
6159 static void
6160 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6161                                          MonoReflectionMethod *method,
6162                                          MonoArray *out_args)
6163 {
6164         MONO_ARCH_SAVE_REGS;
6165
6166         mono_message_init (mono_object_domain (this), this, method, out_args);
6167 }
6168
6169 static MonoBoolean
6170 ves_icall_IsTransparentProxy (MonoObject *proxy)
6171 {
6172         MONO_ARCH_SAVE_REGS;
6173
6174         if (!proxy)
6175                 return 0;
6176
6177         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6178                 return 1;
6179
6180         return 0;
6181 }
6182
6183 static void
6184 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6185 {
6186         MonoClass *klass;
6187         MonoVTable* vtable;
6188
6189         MONO_ARCH_SAVE_REGS;
6190
6191         klass = mono_class_from_mono_type (type->type);
6192         vtable = mono_class_vtable (mono_domain_get (), klass);
6193
6194         if (enable) vtable->remote = 1;
6195         else vtable->remote = 0;
6196 }
6197
6198 static MonoObject *
6199 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6200 {
6201         MonoClass *klass;
6202         MonoDomain *domain;
6203         
6204         MONO_ARCH_SAVE_REGS;
6205
6206         domain = mono_object_domain (type);
6207         klass = mono_class_from_mono_type (type->type);
6208
6209         if (klass->rank >= 1) {
6210                 g_assert (klass->rank == 1);
6211                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6212         } else {
6213                 /* Bypass remoting object creation check */
6214                 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6215         }
6216 }
6217
6218 static MonoString *
6219 ves_icall_System_IO_get_temp_path (void)
6220 {
6221         MONO_ARCH_SAVE_REGS;
6222
6223         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6224 }
6225
6226 static gpointer
6227 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6228 {
6229         MONO_ARCH_SAVE_REGS;
6230
6231         return mono_compile_method (method);
6232 }
6233
6234 static MonoString *
6235 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6236 {
6237         MonoString *mcpath;
6238         gchar *path;
6239
6240         MONO_ARCH_SAVE_REGS;
6241
6242         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6243
6244 #if defined (PLATFORM_WIN32)
6245         /* Avoid mixing '/' and '\\' */
6246         {
6247                 gint i;
6248                 for (i = strlen (path) - 1; i >= 0; i--)
6249                         if (path [i] == '/')
6250                                 path [i] = '\\';
6251         }
6252 #endif
6253         mcpath = mono_string_new (mono_domain_get (), path);
6254         g_free (path);
6255
6256         return mcpath;
6257 }
6258
6259 static MonoString *
6260 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (void)
6261 {
6262         const gchar *machine_config;
6263
6264         MONO_ARCH_SAVE_REGS;
6265
6266         machine_config = mono_get_machine_config ();
6267
6268         if (!machine_config)
6269                 return NULL;
6270
6271         return mono_string_new (mono_domain_get (), machine_config);
6272 }
6273
6274 static MonoString *
6275 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6276 {
6277         MonoString *ipath;
6278         gchar *path;
6279
6280         MONO_ARCH_SAVE_REGS;
6281
6282         path = g_path_get_dirname (mono_get_config_dir ());
6283
6284 #if defined (PLATFORM_WIN32)
6285         /* Avoid mixing '/' and '\\' */
6286         {
6287                 gint i;
6288                 for (i = strlen (path) - 1; i >= 0; i--)
6289                         if (path [i] == '/')
6290                                 path [i] = '\\';
6291         }
6292 #endif
6293         ipath = mono_string_new (mono_domain_get (), path);
6294         g_free (path);
6295
6296         return ipath;
6297 }
6298
6299 static void
6300 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6301 {
6302 #if defined (PLATFORM_WIN32)
6303         OutputDebugString (mono_string_chars (message));
6304 #else
6305         g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6306 #endif
6307 }
6308
6309 /* Only used for value types */
6310 static MonoObject *
6311 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6312 {
6313         MonoClass *klass;
6314         MonoDomain *domain;
6315         
6316         MONO_ARCH_SAVE_REGS;
6317
6318         domain = mono_object_domain (type);
6319         klass = mono_class_from_mono_type (type->type);
6320
6321         if (mono_class_is_nullable (klass))
6322                 /* No arguments -> null */
6323                 return NULL;
6324
6325         return mono_object_new (domain, klass);
6326 }
6327
6328 static MonoReflectionMethod *
6329 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6330 {
6331         MonoClass *klass, *parent;
6332         MonoMethod *method = m->method;
6333         MonoMethod *result = NULL;
6334
6335         MONO_ARCH_SAVE_REGS;
6336
6337         if (method->klass == NULL)
6338                 return m;
6339
6340         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6341             MONO_CLASS_IS_INTERFACE (method->klass) ||
6342             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6343                 return m;
6344
6345         klass = method->klass;
6346         if (klass->generic_class)
6347                 klass = klass->generic_class->container_class;
6348
6349         /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6350         for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6351                 mono_class_setup_vtable (parent);
6352                 if (parent->vtable_size <= method->slot)
6353                         break;
6354                 klass = parent;
6355         }               
6356
6357         if (klass == method->klass)
6358                 return m;
6359
6360         result = klass->vtable [method->slot];
6361         if (result == NULL) {
6362                 /* It is an abstract method */
6363                 gpointer iter = NULL;
6364                 while ((result = mono_class_get_methods (klass, &iter)))
6365                         if (result->slot == method->slot)
6366                                 break;
6367         }
6368
6369         if (result == NULL)
6370                 return m;
6371
6372         return mono_method_get_object (mono_domain_get (), result, NULL);
6373 }
6374
6375 static MonoString*
6376 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6377 {
6378         MonoMethod *method = m->method;
6379
6380         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6381         return m->name;
6382 }
6383
6384 static void
6385 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6386 {
6387         MONO_ARCH_SAVE_REGS;
6388
6389         iter->sig = *(MonoMethodSignature**)argsp;
6390         
6391         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6392         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6393
6394         iter->next_arg = 0;
6395         /* FIXME: it's not documented what start is exactly... */
6396         if (start) {
6397                 iter->args = start;
6398         } else {
6399                 guint32 i, arg_size;
6400                 gint32 align;
6401                 iter->args = argsp + sizeof (gpointer);
6402 #ifndef MONO_ARCH_REGPARMS
6403                 for (i = 0; i < iter->sig->sentinelpos; ++i) {
6404                         arg_size = mono_type_stack_size (iter->sig->params [i], &align);
6405                         iter->args = (char*)iter->args + arg_size;
6406                 }
6407 #endif
6408         }
6409         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6410
6411         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6412 }
6413
6414 static MonoTypedRef
6415 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6416 {
6417         guint32 i, arg_size;
6418         gint32 align;
6419         MonoTypedRef res;
6420         MONO_ARCH_SAVE_REGS;
6421
6422         i = iter->sig->sentinelpos + iter->next_arg;
6423
6424         g_assert (i < iter->sig->param_count);
6425
6426         res.type = iter->sig->params [i];
6427         res.klass = mono_class_from_mono_type (res.type);
6428         /* FIXME: endianess issue... */
6429         res.value = iter->args;
6430         arg_size = mono_type_stack_size (res.type, &align);
6431         iter->args = (char*)iter->args + arg_size;
6432         iter->next_arg++;
6433
6434         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6435
6436         return res;
6437 }
6438
6439 static MonoTypedRef
6440 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6441 {
6442         guint32 i, arg_size;
6443         gint32 align;
6444         MonoTypedRef res;
6445         MONO_ARCH_SAVE_REGS;
6446
6447         i = iter->sig->sentinelpos + iter->next_arg;
6448
6449         g_assert (i < iter->sig->param_count);
6450
6451         while (i < iter->sig->param_count) {
6452                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6453                         continue;
6454                 res.type = iter->sig->params [i];
6455                 res.klass = mono_class_from_mono_type (res.type);
6456                 /* FIXME: endianess issue... */
6457                 res.value = iter->args;
6458                 arg_size = mono_type_stack_size (res.type, &align);
6459                 iter->args = (char*)iter->args + arg_size;
6460                 iter->next_arg++;
6461                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6462                 return res;
6463         }
6464         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6465
6466         res.type = NULL;
6467         res.value = NULL;
6468         res.klass = NULL;
6469         return res;
6470 }
6471
6472 static MonoType*
6473 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6474 {
6475         gint i;
6476         MONO_ARCH_SAVE_REGS;
6477         
6478         i = iter->sig->sentinelpos + iter->next_arg;
6479
6480         g_assert (i < iter->sig->param_count);
6481
6482         return iter->sig->params [i];
6483 }
6484
6485 static MonoObject*
6486 mono_TypedReference_ToObject (MonoTypedRef tref)
6487 {
6488         MONO_ARCH_SAVE_REGS;
6489
6490         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
6491                 MonoObject** objp = tref.value;
6492                 return *objp;
6493         }
6494
6495         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
6496 }
6497
6498 static MonoObject*
6499 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
6500 {
6501         MONO_ARCH_SAVE_REGS;
6502
6503         if (MONO_TYPE_IS_REFERENCE (type)) {
6504                 MonoObject** objp = value;
6505                 return *objp;
6506         }
6507
6508         return mono_value_box (mono_domain_get (), klass, value);
6509 }
6510
6511 static void
6512 prelink_method (MonoMethod *method)
6513 {
6514         const char *exc_class, *exc_arg;
6515         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6516                 return;
6517         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6518         if (exc_class) {
6519                 mono_raise_exception( 
6520                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6521         }
6522         /* create the wrapper, too? */
6523 }
6524
6525 static void
6526 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6527 {
6528         MONO_ARCH_SAVE_REGS;
6529         prelink_method (method->method);
6530 }
6531
6532 static void
6533 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6534 {
6535         MonoClass *klass = mono_class_from_mono_type (type->type);
6536         MonoMethod* m;
6537         gpointer iter = NULL;
6538         MONO_ARCH_SAVE_REGS;
6539
6540         while ((m = mono_class_get_methods (klass, &iter)))
6541                 prelink_method (m);
6542 }
6543
6544 /* These parameters are "readonly" in corlib/System/Char.cs */
6545 static void
6546 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
6547                                             guint8 const **numeric_data,
6548                                             gdouble const **numeric_data_values,
6549                                             guint16 const **to_lower_data_low,
6550                                             guint16 const **to_lower_data_high,
6551                                             guint16 const **to_upper_data_low,
6552                                             guint16 const **to_upper_data_high)
6553 {
6554         *category_data = CategoryData;
6555         *numeric_data = NumericData;
6556         *numeric_data_values = NumericDataValues;
6557         *to_lower_data_low = ToLowerDataLow;
6558         *to_lower_data_high = ToLowerDataHigh;
6559         *to_upper_data_low = ToUpperDataLow;
6560         *to_upper_data_high = ToUpperDataHigh;
6561 }
6562
6563 static gint32
6564 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
6565 {
6566         return method->method->token;
6567 }
6568
6569 /*
6570  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
6571  * and avoid useless allocations.
6572  */
6573 static MonoArray*
6574 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
6575 {
6576         MonoArray *res;
6577         int i, count = 0;
6578         for (i = 0; i < type->num_mods; ++i) {
6579                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
6580                         count++;
6581         }
6582         if (!count)
6583                 return NULL;
6584         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
6585         count = 0;
6586         for (i = 0; i < type->num_mods; ++i) {
6587                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
6588                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
6589                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
6590                         count++;
6591                 }
6592         }
6593         return res;
6594 }
6595
6596 static MonoArray*
6597 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
6598 {
6599         MonoType *type = param->ClassImpl->type;
6600         MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
6601         MonoImage *image = method->method->klass->image;
6602         int pos = param->PositionImpl;
6603         MonoMethodSignature *sig = mono_method_signature (method->method);
6604         if (pos == -1)
6605                 type = sig->ret;
6606         else
6607                 type = sig->params [pos];
6608
6609         return type_array_from_modifiers (image, type, optional);
6610 }
6611
6612 static MonoType*
6613 get_property_type (MonoProperty *prop)
6614 {
6615         MonoMethodSignature *sig;
6616         if (prop->get) {
6617                 sig = mono_method_signature (prop->get);
6618                 return sig->ret;
6619         } else if (prop->set) {
6620                 sig = mono_method_signature (prop->set);
6621                 return sig->params [sig->param_count - 1];
6622         }
6623         return NULL;
6624 }
6625
6626 static MonoArray*
6627 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
6628 {
6629         MonoType *type = get_property_type (property->property);
6630         MonoImage *image = property->klass->image;
6631
6632         if (!type)
6633                 return NULL;
6634         return type_array_from_modifiers (image, type, optional);
6635 }
6636
6637 static MonoBoolean
6638 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
6639 {
6640         MonoCustomAttrInfo *cinfo;
6641         gboolean found;
6642
6643         cinfo = mono_reflection_get_custom_attrs_info (obj);
6644         if (!cinfo)
6645                 return FALSE;
6646         found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
6647         if (!cinfo->cached)
6648                 mono_custom_attrs_free (cinfo);
6649         return found;
6650 }
6651
6652 static MonoArray*
6653 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
6654 {
6655         MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
6656
6657         if (mono_loader_get_last_error ()) {
6658                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
6659                 g_assert_not_reached ();
6660         } else {
6661                 return res;
6662         }
6663 }
6664
6665 static MonoBoolean
6666 GCHandle_CheckCurrentDomain (guint32 gchandle)
6667 {
6668         return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
6669 }
6670
6671 static MonoString*
6672 ves_icall_Mono_Runtime_GetDisplayName (void)
6673 {
6674         static const char display_name_str [] = "Mono " VERSION;
6675         MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
6676         return display_name;
6677 }
6678
6679 const static guchar
6680 dbase64 [] = {
6681         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6682         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6683         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
6684         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
6685         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
6686         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
6687         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
6688         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
6689 };
6690
6691 static MonoArray *
6692 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
6693 {
6694         gint ignored;
6695         gint i;
6696         gunichar2 c;
6697         gunichar2 last, prev_last;
6698         gint olength;
6699         MonoArray *result;
6700         guchar *res_ptr;
6701         gint a [4], b [4];
6702         MonoException *exc;
6703
6704         ignored = 0;
6705         last = prev_last = 0;
6706         for (i = 0; i < ilength; i++) {
6707                 c = start [i];
6708                 if (c >= sizeof (dbase64)) {
6709                         exc = mono_exception_from_name_msg (mono_get_corlib (),
6710                                 "System", "FormatException",
6711                                 "Invalid character found.");
6712                         mono_raise_exception (exc);
6713                 } else if (isspace (c)) {
6714                         ignored++;
6715                 } else {
6716                         prev_last = last;
6717                         last = c;
6718                 }
6719         }
6720
6721         olength = ilength - ignored;
6722
6723         if (allowWhitespaceOnly && olength == 0) {
6724                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
6725         }
6726
6727         if ((olength & 3) != 0 || olength <= 0) {
6728                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
6729                                         "FormatException", "Invalid length.");
6730                 mono_raise_exception (exc);
6731         }
6732
6733         olength = (olength * 3) / 4;
6734         if (last == '=')
6735                 olength--;
6736
6737         if (prev_last == '=')
6738                 olength--;
6739
6740         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
6741         res_ptr = mono_array_addr (result, guchar, 0);
6742         for (i = 0; i < ilength; ) {
6743                 int k;
6744
6745                 for (k = 0; k < 4 && i < ilength;) {
6746                         c = start [i++];
6747                         if (isspace (c))
6748                                 continue;
6749
6750                         a [k] = (guchar) c;
6751                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
6752                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
6753                                         "System", "FormatException",
6754                                         "Invalid character found.");
6755                                 mono_raise_exception (exc);
6756                         }
6757                         k++;
6758                 }
6759
6760                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
6761                 if (a [2] != '=')
6762                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
6763                 if (a [3] != '=')
6764                         *res_ptr++ = (b [2] << 6) | b [3];
6765
6766                 while (i < ilength && isspace (start [i]))
6767                         i++;
6768         }
6769
6770         return result;
6771 }
6772
6773 static MonoArray *
6774 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
6775 {
6776         MONO_ARCH_SAVE_REGS;
6777
6778         return base64_to_byte_array (mono_string_chars (str), 
6779                 mono_string_length (str), allowWhitespaceOnly);
6780 }
6781
6782 static MonoArray *
6783 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
6784 {
6785         MONO_ARCH_SAVE_REGS;
6786
6787         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
6788                 length, FALSE);
6789 }
6790
6791 #define ICALL_TYPE(id,name,first)
6792 #define ICALL(id,name,func) Icall_ ## id,
6793
6794 enum {
6795 #include "metadata/icall-def.h"
6796         Icall_last
6797 };
6798
6799 #undef ICALL_TYPE
6800 #undef ICALL
6801 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
6802 #define ICALL(id,name,func)
6803 enum {
6804 #include "metadata/icall-def.h"
6805         Icall_type_num
6806 };
6807
6808 #undef ICALL_TYPE
6809 #undef ICALL
6810 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
6811 #define ICALL(id,name,func)
6812 typedef struct {
6813         guint16 first_icall;
6814 } IcallTypeDesc;
6815
6816 static const IcallTypeDesc
6817 icall_type_descs [] = {
6818 #include "metadata/icall-def.h"
6819         {Icall_last}
6820 };
6821
6822 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
6823
6824 #undef ICALL_TYPE
6825 #define ICALL_TYPE(id,name,first)
6826 #undef ICALL
6827
6828 #ifdef HAVE_ARRAY_ELEM_INIT
6829 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
6830 #define MSGSTRFIELD1(line) str##line
6831
6832 static const struct msgstrtn_t {
6833 #define ICALL(id,name,func)
6834 #undef ICALL_TYPE
6835 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
6836 #include "metadata/icall-def.h"
6837 #undef ICALL_TYPE
6838 } icall_type_names_str = {
6839 #define ICALL_TYPE(id,name,first) (name),
6840 #include "metadata/icall-def.h"
6841 #undef ICALL_TYPE
6842 };
6843 static const guint16 icall_type_names_idx [] = {
6844 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
6845 #include "metadata/icall-def.h"
6846 #undef ICALL_TYPE
6847 };
6848 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
6849
6850 static const struct msgstr_t {
6851 #undef ICALL
6852 #define ICALL_TYPE(id,name,first)
6853 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
6854 #include "metadata/icall-def.h"
6855 #undef ICALL
6856 } icall_names_str = {
6857 #define ICALL(id,name,func) (name),
6858 #include "metadata/icall-def.h"
6859 #undef ICALL
6860 };
6861 static const guint16 icall_names_idx [] = {
6862 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
6863 #include "metadata/icall-def.h"
6864 #undef ICALL
6865 };
6866 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
6867
6868 #else
6869
6870 #undef ICALL_TYPE
6871 #undef ICALL
6872 #define ICALL_TYPE(id,name,first) name,
6873 #define ICALL(id,name,func)
6874 static const char* const
6875 icall_type_names [] = {
6876 #include "metadata/icall-def.h"
6877         NULL
6878 };
6879
6880 #define icall_type_name_get(id) (icall_type_names [(id)])
6881
6882 #undef ICALL_TYPE
6883 #undef ICALL
6884 #define ICALL_TYPE(id,name,first)
6885 #define ICALL(id,name,func) name,
6886 static const char* const
6887 icall_names [] = {
6888 #include "metadata/icall-def.h"
6889         NULL
6890 };
6891 #define icall_name_get(id) icall_names [(id)]
6892
6893 #endif /* !HAVE_ARRAY_ELEM_INIT */
6894
6895 #undef ICALL_TYPE
6896 #undef ICALL
6897 #define ICALL_TYPE(id,name,first)
6898 #define ICALL(id,name,func) func,
6899 static const gconstpointer
6900 icall_functions [] = {
6901 #include "metadata/icall-def.h"
6902         NULL
6903 };
6904
6905 static GHashTable *icall_hash = NULL;
6906 static GHashTable *jit_icall_hash_name = NULL;
6907 static GHashTable *jit_icall_hash_addr = NULL;
6908
6909 void
6910 mono_icall_init (void)
6911 {
6912         int i = 0;
6913
6914         /* check that tables are sorted: disable in release */
6915         if (TRUE) {
6916                 int j;
6917                 const char *prev_class = NULL;
6918                 const char *prev_method;
6919                 
6920                 for (i = 0; i < Icall_type_num; ++i) {
6921                         const IcallTypeDesc *desc;
6922                         int num_icalls;
6923                         prev_method = NULL;
6924                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
6925                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
6926                         prev_class = icall_type_name_get (i);
6927                         desc = &icall_type_descs [i];
6928                         num_icalls = icall_desc_num_icalls (desc);
6929                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
6930                         for (j = 0; j < num_icalls; ++j) {
6931                                 const char *methodn = icall_name_get (desc->first_icall + j);
6932                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
6933                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
6934                                 prev_method = methodn;
6935                         }
6936                 }
6937         }
6938
6939         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
6940 }
6941
6942 void
6943 mono_icall_cleanup (void)
6944 {
6945         g_hash_table_destroy (icall_hash);
6946         g_hash_table_destroy (jit_icall_hash_name);
6947         g_hash_table_destroy (jit_icall_hash_addr);
6948 }
6949
6950 void
6951 mono_add_internal_call (const char *name, gconstpointer method)
6952 {
6953         mono_loader_lock ();
6954
6955         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
6956
6957         mono_loader_unlock ();
6958 }
6959
6960 #ifdef HAVE_ARRAY_ELEM_INIT
6961 static int
6962 compare_method_imap (const void *key, const void *elem)
6963 {
6964         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
6965         return strcmp (key, method_name);
6966 }
6967
6968 static gpointer
6969 find_method_icall (const IcallTypeDesc *imap, const char *name)
6970 {
6971         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
6972         if (!nameslot)
6973                 return NULL;
6974         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
6975 }
6976
6977 static int
6978 compare_class_imap (const void *key, const void *elem)
6979 {
6980         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
6981         return strcmp (key, class_name);
6982 }
6983
6984 static const IcallTypeDesc*
6985 find_class_icalls (const char *name)
6986 {
6987         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
6988         if (!nameslot)
6989                 return NULL;
6990         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
6991 }
6992
6993 #else
6994 static int
6995 compare_method_imap (const void *key, const void *elem)
6996 {
6997         const char** method_name = (const char**)elem;
6998         return strcmp (key, *method_name);
6999 }
7000
7001 static gpointer
7002 find_method_icall (const IcallTypeDesc *imap, const char *name)
7003 {
7004         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7005         if (!nameslot)
7006                 return NULL;
7007         return (gpointer)icall_functions [(nameslot - icall_names)];
7008 }
7009
7010 static int
7011 compare_class_imap (const void *key, const void *elem)
7012 {
7013         const char** class_name = (const char**)elem;
7014         return strcmp (key, *class_name);
7015 }
7016
7017 static const IcallTypeDesc*
7018 find_class_icalls (const char *name)
7019 {
7020         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7021         if (!nameslot)
7022                 return NULL;
7023         return &icall_type_descs [nameslot - icall_type_names];
7024 }
7025
7026 #endif
7027
7028 /* 
7029  * we should probably export this as an helper (handle nested types).
7030  * Returns the number of chars written in buf.
7031  */
7032 static int
7033 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7034 {
7035         int nspacelen, cnamelen;
7036         nspacelen = strlen (klass->name_space);
7037         cnamelen = strlen (klass->name);
7038         if (nspacelen + cnamelen + 2 > bufsize)
7039                 return 0;
7040         if (nspacelen) {
7041                 memcpy (buf, klass->name_space, nspacelen);
7042                 buf [nspacelen ++] = '.';
7043         }
7044         memcpy (buf + nspacelen, klass->name, cnamelen);
7045         buf [nspacelen + cnamelen] = 0;
7046         return nspacelen + cnamelen;
7047 }
7048
7049 gpointer
7050 mono_lookup_internal_call (MonoMethod *method)
7051 {
7052         char *sigstart;
7053         char *tmpsig;
7054         char mname [2048];
7055         int typelen = 0, mlen, siglen;
7056         gpointer res;
7057         const IcallTypeDesc *imap;
7058
7059         g_assert (method != NULL);
7060
7061         if (method->is_inflated)
7062                 method = ((MonoMethodInflated *) method)->declaring;
7063
7064         if (method->klass->nested_in) {
7065                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7066                 if (!pos)
7067                         return NULL;
7068
7069                 mname [pos++] = '/';
7070                 mname [pos] = 0;
7071
7072                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7073                 if (!typelen)
7074                         return NULL;
7075
7076                 typelen += pos;
7077         } else {
7078                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7079                 if (!typelen)
7080                         return NULL;
7081         }
7082
7083         imap = find_class_icalls (mname);
7084
7085         mname [typelen] = ':';
7086         mname [typelen + 1] = ':';
7087
7088         mlen = strlen (method->name);
7089         memcpy (mname + typelen + 2, method->name, mlen);
7090         sigstart = mname + typelen + 2 + mlen;
7091         *sigstart = 0;
7092
7093         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7094         siglen = strlen (tmpsig);
7095         if (typelen + mlen + siglen + 6 > sizeof (mname))
7096                 return NULL;
7097         sigstart [0] = '(';
7098         memcpy (sigstart + 1, tmpsig, siglen);
7099         sigstart [siglen + 1] = ')';
7100         sigstart [siglen + 2] = 0;
7101         g_free (tmpsig);
7102         
7103         mono_loader_lock ();
7104
7105         res = g_hash_table_lookup (icall_hash, mname);
7106         if (res) {
7107                 mono_loader_unlock ();
7108                 return res;
7109         }
7110         /* try without signature */
7111         *sigstart = 0;
7112         res = g_hash_table_lookup (icall_hash, mname);
7113         if (res) {
7114                 mono_loader_unlock ();
7115                 return res;
7116         }
7117
7118         /* it wasn't found in the static call tables */
7119         if (!imap) {
7120                 mono_loader_unlock ();
7121                 return NULL;
7122         }
7123         res = find_method_icall (imap, sigstart - mlen);
7124         if (res) {
7125                 mono_loader_unlock ();
7126                 return res;
7127         }
7128         /* try _with_ signature */
7129         *sigstart = '(';
7130         res = find_method_icall (imap, sigstart - mlen);
7131         if (res) {
7132                 mono_loader_unlock ();
7133                 return res;
7134         }
7135
7136         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7137         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7138         g_print ("The out of sync library is: %s\n", method->klass->image->name);
7139         g_print ("\nWhen you update one from cvs you need to update, compile and install\nthe other too.\n");
7140         g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
7141         g_print ("If you see other errors or faults after this message they are probably related\n");
7142         g_print ("and you need to fix your mono install first.\n");
7143
7144         mono_loader_unlock ();
7145
7146         return NULL;
7147 }
7148
7149 static MonoType*
7150 type_from_typename (char *typename)
7151 {
7152         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
7153
7154         if (!strcmp (typename, "int"))
7155                 klass = mono_defaults.int_class;
7156         else if (!strcmp (typename, "ptr"))
7157                 klass = mono_defaults.int_class;
7158         else if (!strcmp (typename, "void"))
7159                 klass = mono_defaults.void_class;
7160         else if (!strcmp (typename, "int32"))
7161                 klass = mono_defaults.int32_class;
7162         else if (!strcmp (typename, "uint32"))
7163                 klass = mono_defaults.uint32_class;
7164         else if (!strcmp (typename, "int8"))
7165                 klass = mono_defaults.sbyte_class;
7166         else if (!strcmp (typename, "uint8"))
7167                 klass = mono_defaults.byte_class;
7168         else if (!strcmp (typename, "int16"))
7169                 klass = mono_defaults.int16_class;
7170         else if (!strcmp (typename, "uint16"))
7171                 klass = mono_defaults.uint16_class;
7172         else if (!strcmp (typename, "long"))
7173                 klass = mono_defaults.int64_class;
7174         else if (!strcmp (typename, "ulong"))
7175                 klass = mono_defaults.uint64_class;
7176         else if (!strcmp (typename, "float"))
7177                 klass = mono_defaults.single_class;
7178         else if (!strcmp (typename, "double"))
7179                 klass = mono_defaults.double_class;
7180         else if (!strcmp (typename, "object"))
7181                 klass = mono_defaults.object_class;
7182         else if (!strcmp (typename, "obj"))
7183                 klass = mono_defaults.object_class;
7184         else {
7185                 g_error (typename);
7186                 g_assert_not_reached ();
7187         }
7188         return &klass->byval_arg;
7189 }
7190
7191 MonoMethodSignature*
7192 mono_create_icall_signature (const char *sigstr)
7193 {
7194         gchar **parts;
7195         int i, len;
7196         gchar **tmp;
7197         MonoMethodSignature *res;
7198
7199         mono_loader_lock ();
7200         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7201         if (res) {
7202                 mono_loader_unlock ();
7203                 return res;
7204         }
7205
7206         parts = g_strsplit (sigstr, " ", 256);
7207
7208         tmp = parts;
7209         len = 0;
7210         while (*tmp) {
7211                 len ++;
7212                 tmp ++;
7213         }
7214
7215         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7216         res->pinvoke = 1;
7217
7218 #ifdef PLATFORM_WIN32
7219         /* 
7220          * Under windows, the default pinvoke calling convention is STDCALL but
7221          * we need CDECL.
7222          */
7223         res->call_convention = MONO_CALL_C;
7224 #endif
7225
7226         res->ret = type_from_typename (parts [0]);
7227         for (i = 1; i < len; ++i) {
7228                 res->params [i - 1] = type_from_typename (parts [i]);
7229         }
7230
7231         g_strfreev (parts);
7232
7233         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7234
7235         mono_loader_unlock ();
7236
7237         return res;
7238 }
7239
7240 MonoJitICallInfo *
7241 mono_find_jit_icall_by_name (const char *name)
7242 {
7243         MonoJitICallInfo *info;
7244         g_assert (jit_icall_hash_name);
7245
7246         mono_loader_lock ();
7247         info = g_hash_table_lookup (jit_icall_hash_name, name);
7248         mono_loader_unlock ();
7249         return info;
7250 }
7251
7252 MonoJitICallInfo *
7253 mono_find_jit_icall_by_addr (gconstpointer addr)
7254 {
7255         MonoJitICallInfo *info;
7256         g_assert (jit_icall_hash_addr);
7257
7258         mono_loader_lock ();
7259         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7260         mono_loader_unlock ();
7261
7262         return info;
7263 }
7264
7265 void
7266 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7267 {
7268         mono_loader_lock ();
7269         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7270         mono_loader_unlock ();
7271 }
7272
7273 MonoJitICallInfo *
7274 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7275 {
7276         MonoJitICallInfo *info;
7277         
7278         g_assert (func);
7279         g_assert (name);
7280
7281         mono_loader_lock ();
7282
7283         if (!jit_icall_hash_name) {
7284                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7285                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7286         }
7287
7288         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7289                 g_warning ("jit icall already defined \"%s\"\n", name);
7290                 g_assert_not_reached ();
7291         }
7292
7293         info = g_new0 (MonoJitICallInfo, 1);
7294         
7295         info->name = name;
7296         info->func = func;
7297         info->sig = sig;
7298
7299         if (is_save) {
7300                 info->wrapper = func;
7301         } else {
7302                 info->wrapper = NULL;
7303         }
7304
7305         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7306         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7307
7308         mono_loader_unlock ();
7309         return info;
7310 }