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