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