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