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