2009-02-10 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * 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 MonoObject *
3022 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc) 
3023 {
3024         /* 
3025          * Invoke from reflection is supposed to always be a virtual call (the API
3026          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3027          * greater flexibility.
3028          */
3029         MonoMethod *m = method->method;
3030         int pcount;
3031         void *obj = this;
3032
3033         MONO_ARCH_SAVE_REGS;
3034
3035         *exc = NULL;
3036
3037         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
3038                         mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
3039                 ensure_reflection_security ();
3040
3041         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3042                 if (this) {
3043                         if (!mono_object_isinst (this, m->klass)) {
3044                                 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3045                                 return NULL;
3046                         }
3047                         m = mono_object_get_virtual_method (this, m);
3048                         /* must pass the pointer to the value for valuetype methods */
3049                         if (m->klass->valuetype)
3050                                 obj = mono_object_unbox (this);
3051                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3052                         *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3053                         return NULL;
3054                 }
3055         }
3056
3057         pcount = params? mono_array_length (params): 0;
3058         if (pcount != mono_method_signature (m)->param_count) {
3059                 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3060                 return NULL;
3061         }
3062
3063         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3064                 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3065                 return NULL;
3066         }
3067
3068         if (m->klass->image->assembly->ref_only) {
3069                 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3070                 return NULL;
3071         }
3072         
3073         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3074                 int i;
3075                 mono_array_size_t *lengths;
3076                 mono_array_size_t *lower_bounds;
3077                 pcount = mono_array_length (params);
3078                 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3079                 for (i = 0; i < pcount; ++i)
3080                         lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3081
3082                 if (m->klass->rank == pcount) {
3083                         /* Only lengths provided. */
3084                         lower_bounds = NULL;
3085                 } else {
3086                         g_assert (pcount == (m->klass->rank * 2));
3087                         /* lower bounds are first. */
3088                         lower_bounds = lengths;
3089                         lengths += m->klass->rank;
3090                 }
3091
3092                 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3093         }
3094         return mono_runtime_invoke_array (m, obj, params, NULL);
3095 }
3096
3097 static MonoObject *
3098 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
3099 {
3100         MonoDomain *domain = mono_object_domain (method); 
3101         MonoMethod *m = method->method;
3102         MonoMethodSignature *sig = mono_method_signature (m);
3103         MonoArray *out_args;
3104         MonoObject *result;
3105         int i, j, outarg_count = 0;
3106
3107         MONO_ARCH_SAVE_REGS;
3108
3109         if (m->klass == mono_defaults.object_class) {
3110
3111                 if (!strcmp (m->name, "FieldGetter")) {
3112                         MonoClass *k = this->vtable->klass;
3113                         MonoString *name;
3114                         char *str;
3115                         
3116                         /* If this is a proxy, then it must be a CBO */
3117                         if (k == mono_defaults.transparent_proxy_class) {
3118                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3119                                 this = tp->rp->unwrapped_server;
3120                                 g_assert (this);
3121                                 k = this->vtable->klass;
3122                         }
3123                         
3124                         name = mono_array_get (params, MonoString *, 1);
3125                         str = mono_string_to_utf8 (name);
3126                 
3127                         do {
3128                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
3129                                 if (field) {
3130                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
3131                                         if (field_klass->valuetype)
3132                                                 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3133                                         else 
3134                                                 result = *((gpointer *)((char *)this + field->offset));
3135                                 
3136                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3137                                         *outArgs = out_args;
3138                                         mono_array_setref (out_args, 0, result);
3139                                         g_free (str);
3140                                         return NULL;
3141                                 }
3142                                 k = k->parent;
3143                         } while (k);
3144
3145                         g_free (str);
3146                         g_assert_not_reached ();
3147
3148                 } else if (!strcmp (m->name, "FieldSetter")) {
3149                         MonoClass *k = this->vtable->klass;
3150                         MonoString *name;
3151                         guint32 size;
3152                         gint32 align;
3153                         char *str;
3154                         
3155                         /* If this is a proxy, then it must be a CBO */
3156                         if (k == mono_defaults.transparent_proxy_class) {
3157                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3158                                 this = tp->rp->unwrapped_server;
3159                                 g_assert (this);
3160                                 k = this->vtable->klass;
3161                         }
3162                         
3163                         name = mono_array_get (params, MonoString *, 1);
3164                         str = mono_string_to_utf8 (name);
3165                 
3166                         do {
3167                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
3168                                 if (field) {
3169                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
3170                                         MonoObject *val = mono_array_get (params, gpointer, 2);
3171
3172                                         if (field_klass->valuetype) {
3173                                                 size = mono_type_size (field->type, &align);
3174 #ifdef HAVE_SGEN_GC
3175                                                 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3176 #endif
3177                                                 memcpy ((char *)this + field->offset, 
3178                                                         ((char *)val) + sizeof (MonoObject), size);
3179                                         } else {
3180                                                 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3181                                         }
3182                                 
3183                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3184                                         *outArgs = out_args;
3185
3186                                         g_free (str);
3187                                         return NULL;
3188                                 }
3189                                 
3190                                 k = k->parent;
3191                         } while (k);
3192
3193                         g_free (str);
3194                         g_assert_not_reached ();
3195
3196                 }
3197         }
3198
3199         for (i = 0; i < mono_array_length (params); i++) {
3200                 if (sig->params [i]->byref) 
3201                         outarg_count++;
3202         }
3203
3204         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3205         
3206         /* handle constructors only for objects already allocated */
3207         if (!strcmp (method->method->name, ".ctor"))
3208                 g_assert (this);
3209
3210         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3211         g_assert (!method->method->klass->valuetype);
3212         result = mono_runtime_invoke_array (method->method, this, params, NULL);
3213
3214         for (i = 0, j = 0; i < mono_array_length (params); i++) {
3215                 if (sig->params [i]->byref) {
3216                         gpointer arg;
3217                         arg = mono_array_get (params, gpointer, i);
3218                         mono_array_setref (out_args, j, arg);
3219                         j++;
3220                 }
3221         }
3222
3223         *outArgs = out_args;
3224
3225         return result;
3226 }
3227
3228 static guint64
3229 read_enum_value (char *mem, int type)
3230 {
3231         switch (type) {
3232         case MONO_TYPE_U1:
3233                 return *(guint8*)mem;
3234         case MONO_TYPE_I1:
3235                 return *(gint8*)mem;
3236         case MONO_TYPE_U2:
3237                 return *(guint16*)mem;
3238         case MONO_TYPE_I2:
3239                 return *(gint16*)mem;
3240         case MONO_TYPE_U4:
3241                 return *(guint32*)mem;
3242         case MONO_TYPE_I4:
3243                 return *(gint32*)mem;
3244         case MONO_TYPE_U8:
3245                 return *(guint64*)mem;
3246         case MONO_TYPE_I8:
3247                 return *(gint64*)mem;
3248         default:
3249                 g_assert_not_reached ();
3250         }
3251         return 0;
3252 }
3253
3254 static void
3255 write_enum_value (char *mem, int type, guint64 value)
3256 {
3257         switch (type) {
3258         case MONO_TYPE_U1:
3259         case MONO_TYPE_I1: {
3260                 guint8 *p = (guint8*)mem;
3261                 *p = value;
3262                 break;
3263         }
3264         case MONO_TYPE_U2:
3265         case MONO_TYPE_I2: {
3266                 guint16 *p = (void*)mem;
3267                 *p = value;
3268                 break;
3269         }
3270         case MONO_TYPE_U4:
3271         case MONO_TYPE_I4: {
3272                 guint32 *p = (void*)mem;
3273                 *p = value;
3274                 break;
3275         }
3276         case MONO_TYPE_U8:
3277         case MONO_TYPE_I8: {
3278                 guint64 *p = (void*)mem;
3279                 *p = value;
3280                 break;
3281         }
3282         default:
3283                 g_assert_not_reached ();
3284         }
3285         return;
3286 }
3287
3288 static MonoObject *
3289 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3290 {
3291         MonoDomain *domain; 
3292         MonoClass *enumc, *objc;
3293         MonoObject *res;
3294         guint64 val;
3295         
3296         MONO_ARCH_SAVE_REGS;
3297
3298         MONO_CHECK_ARG_NULL (enumType);
3299         MONO_CHECK_ARG_NULL (value);
3300
3301         domain = mono_object_domain (enumType); 
3302         enumc = mono_class_from_mono_type (enumType->type);
3303         objc = value->vtable->klass;
3304
3305         if (!enumc->enumtype)
3306                 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3307         if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3308                 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."));
3309
3310         res = mono_object_new (domain, enumc);
3311         val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3312         write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3313
3314         return res;
3315 }
3316
3317 static MonoObject *
3318 ves_icall_System_Enum_get_value (MonoObject *this)
3319 {
3320         MonoObject *res;
3321         MonoClass *enumc;
3322         gpointer dst;
3323         gpointer src;
3324         int size;
3325
3326         MONO_ARCH_SAVE_REGS;
3327
3328         if (!this)
3329                 return NULL;
3330
3331         g_assert (this->vtable->klass->enumtype);
3332         
3333         enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3334         res = mono_object_new (mono_object_domain (this), enumc);
3335         dst = (char *)res + sizeof (MonoObject);
3336         src = (char *)this + sizeof (MonoObject);
3337         size = mono_class_value_size (enumc, NULL);
3338
3339         memcpy (dst, src, size);
3340
3341         return res;
3342 }
3343
3344 static MonoReflectionType *
3345 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3346 {
3347         MONO_ARCH_SAVE_REGS;
3348
3349         return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3350 }
3351
3352 static int
3353 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3354 {
3355         gpointer data = (char *)this + sizeof (MonoObject);
3356         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3357         g_assert (basetype);
3358
3359         switch (basetype->type) {
3360                 case MONO_TYPE_I1:      
3361                         return *((gint8*)data);
3362                 case MONO_TYPE_U1:
3363                         return *((guint8*)data);
3364                 case MONO_TYPE_CHAR:
3365                 case MONO_TYPE_U2:
3366                         return *((guint16*)data);
3367                 
3368                 case MONO_TYPE_I2:
3369                         return *((gint16*)data);
3370                 case MONO_TYPE_U4:
3371                         return *((guint32*)data);
3372                 case MONO_TYPE_I4:
3373                         return *((gint32*)data);
3374                 case MONO_TYPE_U8:
3375                 case MONO_TYPE_I8: {
3376                         gint64 value = *((gint64*)data);
3377                         return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3378                 }
3379                 default:
3380                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3381         }
3382         return 0;
3383 }
3384
3385 static void
3386 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3387 {
3388         MonoDomain *domain = mono_object_domain (type); 
3389         MonoClass *enumc = mono_class_from_mono_type (type->type);
3390         guint j = 0, nvalues, crow;
3391         gpointer iter;
3392         MonoClassField *field;
3393
3394         MONO_ARCH_SAVE_REGS;
3395
3396         info->utype = mono_type_get_object (domain, mono_class_enum_basetype (enumc));
3397         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3398         info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3399         info->values = mono_array_new (domain, enumc, nvalues);
3400         
3401         crow = -1;
3402         iter = NULL;
3403         while ((field = mono_class_get_fields (enumc, &iter))) {
3404                 const char *p;
3405                 int len;
3406                 MonoTypeEnum def_type;
3407                 
3408                 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3409                         continue;
3410                 if (mono_field_is_deleted (field))
3411                         continue;
3412                 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3413
3414                 p = mono_class_get_field_default_value (field, &def_type);
3415                 len = mono_metadata_decode_blob_size (p, &p);
3416                 switch (mono_class_enum_basetype (enumc)->type) {
3417                 case MONO_TYPE_U1:
3418                 case MONO_TYPE_I1:
3419                         mono_array_set (info->values, gchar, j, *p);
3420                         break;
3421                 case MONO_TYPE_CHAR:
3422                 case MONO_TYPE_U2:
3423                 case MONO_TYPE_I2:
3424                         mono_array_set (info->values, gint16, j, read16 (p));
3425                         break;
3426                 case MONO_TYPE_U4:
3427                 case MONO_TYPE_I4:
3428                         mono_array_set (info->values, gint32, j, read32 (p));
3429                         break;
3430                 case MONO_TYPE_U8:
3431                 case MONO_TYPE_I8:
3432                         mono_array_set (info->values, gint64, j, read64 (p));
3433                         break;
3434                 default:
3435                         g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3436                 }
3437                 ++j;
3438         }
3439 }
3440
3441 enum {
3442         BFLAGS_IgnoreCase = 1,
3443         BFLAGS_DeclaredOnly = 2,
3444         BFLAGS_Instance = 4,
3445         BFLAGS_Static = 8,
3446         BFLAGS_Public = 0x10,
3447         BFLAGS_NonPublic = 0x20,
3448         BFLAGS_FlattenHierarchy = 0x40,
3449         BFLAGS_InvokeMethod = 0x100,
3450         BFLAGS_CreateInstance = 0x200,
3451         BFLAGS_GetField = 0x400,
3452         BFLAGS_SetField = 0x800,
3453         BFLAGS_GetProperty = 0x1000,
3454         BFLAGS_SetProperty = 0x2000,
3455         BFLAGS_ExactBinding = 0x10000,
3456         BFLAGS_SuppressChangeType = 0x20000,
3457         BFLAGS_OptionalParamBinding = 0x40000
3458 };
3459
3460 static MonoReflectionField *
3461 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3462 {
3463         MonoDomain *domain; 
3464         MonoClass *startklass, *klass;
3465         int match;
3466         MonoClassField *field;
3467         gpointer iter;
3468         char *utf8_name;
3469         int (*compare_func) (const char *s1, const char *s2) = NULL;
3470         domain = ((MonoObject *)type)->vtable->domain;
3471         klass = startklass = mono_class_from_mono_type (type->type);
3472
3473         MONO_ARCH_SAVE_REGS;
3474
3475         if (!name)
3476                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3477         if (type->type->byref)
3478                 return NULL;
3479
3480         compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3481
3482 handle_parent:
3483         if (klass->exception_type != MONO_EXCEPTION_NONE)
3484                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3485
3486         iter = NULL;
3487         while ((field = mono_class_get_fields (klass, &iter))) {
3488                 match = 0;
3489
3490                 if (field->type == NULL)
3491                         continue;
3492                 if (mono_field_is_deleted (field))
3493                         continue;
3494                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3495                         if (bflags & BFLAGS_Public)
3496                                 match++;
3497                 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3498                         if (bflags & BFLAGS_NonPublic) {
3499                                 match++;
3500                         }
3501                 }
3502                 if (!match)
3503                         continue;
3504                 match = 0;
3505                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3506                         if (bflags & BFLAGS_Static)
3507                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3508                                         match++;
3509                 } else {
3510                         if (bflags & BFLAGS_Instance)
3511                                 match++;
3512                 }
3513
3514                 if (!match)
3515                         continue;
3516                 
3517                 utf8_name = mono_string_to_utf8 (name);
3518
3519                 if (compare_func (mono_field_get_name (field), utf8_name)) {
3520                         g_free (utf8_name);
3521                         continue;
3522                 }
3523                 g_free (utf8_name);
3524                 
3525                 return mono_field_get_object (domain, klass, field);
3526         }
3527         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3528                 goto handle_parent;
3529
3530         return NULL;
3531 }
3532
3533 static MonoArray*
3534 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3535 {
3536         MonoDomain *domain; 
3537         MonoClass *startklass, *klass, *refklass;
3538         MonoArray *res;
3539         MonoObject *member;
3540         int i, len, match;
3541         gpointer iter;
3542         MonoClassField *field;
3543
3544         MONO_ARCH_SAVE_REGS;
3545
3546         domain = ((MonoObject *)type)->vtable->domain;
3547         if (type->type->byref)
3548                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3549         klass = startklass = mono_class_from_mono_type (type->type);
3550         refklass = mono_class_from_mono_type (reftype->type);
3551
3552         i = 0;
3553         len = 2;
3554         res = mono_array_new (domain, mono_defaults.field_info_class, len);
3555 handle_parent:  
3556         if (klass->exception_type != MONO_EXCEPTION_NONE)
3557                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3558
3559         iter = NULL;
3560         while ((field = mono_class_get_fields (klass, &iter))) {
3561                 match = 0;
3562                 if (mono_field_is_deleted (field))
3563                         continue;
3564                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3565                         if (bflags & BFLAGS_Public)
3566                                 match++;
3567                 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3568                         if (bflags & BFLAGS_NonPublic) {
3569                                 match++;
3570                         }
3571                 }
3572                 if (!match)
3573                         continue;
3574                 match = 0;
3575                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3576                         if (bflags & BFLAGS_Static)
3577                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3578                                         match++;
3579                 } else {
3580                         if (bflags & BFLAGS_Instance)
3581                                 match++;
3582                 }
3583
3584                 if (!match)
3585                         continue;
3586                 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3587                 if (i >= len) {
3588                         MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3589                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3590                         len *= 2;
3591                         res = new_res;
3592                 }
3593                 mono_array_setref (res, i, member);
3594                 ++i;
3595         }
3596         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3597                 goto handle_parent;
3598         if (i != len) {
3599                 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3600                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3601                 res = new_res;
3602                 /*
3603                  * Better solution for the new GC.
3604                  * res->max_length = i;
3605                  */
3606         }
3607         return res;
3608 }
3609
3610 static gboolean
3611 method_nonpublic (MonoMethod* method, gboolean start_klass)
3612 {
3613         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3614                 case METHOD_ATTRIBUTE_ASSEM:
3615                         return (start_klass || mono_defaults.generic_ilist_class);
3616                 case METHOD_ATTRIBUTE_PRIVATE:
3617                         return start_klass;
3618                 case METHOD_ATTRIBUTE_PUBLIC:
3619                         return FALSE;
3620                 default:
3621                         return TRUE;
3622         }
3623 }
3624
3625 static MonoArray*
3626 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3627 {
3628         static MonoClass *MethodInfo_array;
3629         MonoDomain *domain; 
3630         MonoClass *startklass, *klass, *refklass;
3631         MonoArray *res;
3632         MonoMethod *method;
3633         gpointer iter;
3634         MonoObject *member;
3635         int i, len, match, nslots;
3636         guint32 method_slots_default [8];
3637         guint32 *method_slots;
3638         gchar *mname = NULL;
3639         int (*compare_func) (const char *s1, const char *s2) = NULL;
3640         MonoVTable *array_vtable;
3641                 
3642         MONO_ARCH_SAVE_REGS;
3643
3644         if (!MethodInfo_array) {
3645                 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3646                 mono_memory_barrier ();
3647                 MethodInfo_array = klass;
3648         }
3649
3650         domain = ((MonoObject *)type)->vtable->domain;
3651         array_vtable = mono_class_vtable (domain, MethodInfo_array);
3652         if (type->type->byref)
3653                 return mono_array_new_specific (array_vtable, 0);
3654         klass = startklass = mono_class_from_mono_type (type->type);
3655         refklass = mono_class_from_mono_type (reftype->type);
3656         len = 0;
3657         if (name != NULL) {
3658                 mname = mono_string_to_utf8 (name);
3659                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3660         }
3661
3662         /* An optimization for calls made from Delegate:CreateDelegate () */
3663         if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3664                 method = mono_get_delegate_invoke (klass);
3665
3666                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3667                 
3668                 res = mono_array_new_specific (array_vtable, 1);
3669                 mono_array_setref (res, 0, member);
3670                 return res;
3671         }
3672
3673         mono_class_setup_vtable (klass);
3674
3675         if (is_generic_parameter (type->type))
3676                 nslots = klass->parent->vtable_size;
3677         else
3678                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3679         if (nslots >= sizeof (method_slots_default) * 8) {
3680                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3681         } else {
3682                 method_slots = method_slots_default;
3683                 memset (method_slots, 0, sizeof (method_slots_default));
3684         }
3685         i = 0;
3686         len = 1;
3687         res = mono_array_new_specific (array_vtable, len);
3688 handle_parent:
3689         mono_class_setup_vtable (klass);
3690         if (klass->exception_type != MONO_EXCEPTION_NONE)
3691                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3692
3693         iter = NULL;
3694         while ((method = mono_class_get_methods (klass, &iter))) {
3695                 match = 0;
3696                 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3697                         continue;
3698                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3699                         if (bflags & BFLAGS_Public)
3700                                 match++;
3701                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3702                                 match++;
3703                 }
3704                 if (!match)
3705                         continue;
3706                 match = 0;
3707                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3708                         if (bflags & BFLAGS_Static)
3709                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3710                                         match++;
3711                 } else {
3712                         if (bflags & BFLAGS_Instance)
3713                                 match++;
3714                 }
3715
3716                 if (!match)
3717                         continue;
3718
3719                 if (name != NULL) {
3720                         if (compare_func (mname, method->name))
3721                                 continue;
3722                 }
3723                 
3724                 match = 0;
3725                 if (method->slot != -1) {
3726                         g_assert (method->slot < nslots);
3727                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3728                                 continue;
3729                         method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3730                 }
3731                 
3732                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3733                 
3734                 if (i >= len) {
3735                         MonoArray *new_res = mono_array_new_specific (array_vtable, len * 2);
3736                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3737                         len *= 2;
3738                         res = new_res;
3739                 }
3740                 mono_array_setref (res, i, member);
3741                 ++i;
3742         }
3743         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3744                 goto handle_parent;
3745
3746         g_free (mname);
3747         if (method_slots != method_slots_default)
3748                 g_free (method_slots);
3749         if (i != len) {
3750                 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3751                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3752                 res = new_res;
3753                 /*
3754                  * Better solution for the new GC.
3755                  * res->max_length = i;
3756                  */
3757         }
3758         return res;
3759 }
3760
3761 static MonoArray*
3762 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3763 {
3764         MonoDomain *domain; 
3765         static MonoClass *System_Reflection_ConstructorInfo;
3766         MonoClass *startklass, *klass, *refklass;
3767         MonoArray *res;
3768         MonoMethod *method;
3769         MonoObject *member;
3770         int i, len, match;
3771         gpointer iter = NULL;
3772         
3773         MONO_ARCH_SAVE_REGS;
3774
3775         domain = ((MonoObject *)type)->vtable->domain;
3776         if (type->type->byref)
3777                 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3778         klass = startklass = mono_class_from_mono_type (type->type);
3779         refklass = mono_class_from_mono_type (reftype->type);
3780
3781         if (klass->exception_type != MONO_EXCEPTION_NONE)
3782                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3783
3784         if (!System_Reflection_ConstructorInfo)
3785                 System_Reflection_ConstructorInfo = mono_class_from_name (
3786                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3787
3788         i = 0;
3789         len = 2;
3790         res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3791         iter = NULL;
3792         while ((method = mono_class_get_methods (klass, &iter))) {
3793                 match = 0;
3794                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3795                         continue;
3796                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3797                         if (bflags & BFLAGS_Public)
3798                                 match++;
3799                 } else {
3800                         if (bflags & BFLAGS_NonPublic)
3801                                 match++;
3802                 }
3803                 if (!match)
3804                         continue;
3805                 match = 0;
3806                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3807                         if (bflags & BFLAGS_Static)
3808                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3809                                         match++;
3810                 } else {
3811                         if (bflags & BFLAGS_Instance)
3812                                 match++;
3813                 }
3814
3815                 if (!match)
3816                         continue;
3817                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3818
3819                 if (i >= len) {
3820                         MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3821                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3822                         len *= 2;
3823                         res = new_res;
3824                 }
3825                 mono_array_setref (res, i, member);
3826                 ++i;
3827         }
3828         if (i != len) {
3829                 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3830                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3831                 res = new_res;
3832                 /*
3833                  * Better solution for the new GC.
3834                  * res->max_length = i;
3835                  */
3836         }
3837         return res;
3838 }
3839
3840 static guint
3841 property_hash (gconstpointer data)
3842 {
3843         MonoProperty *prop = (MonoProperty*)data;
3844
3845         return g_str_hash (prop->name);
3846 }
3847
3848 static gboolean
3849 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3850 {
3851         // Properties are hide-by-name-and-signature
3852         if (!g_str_equal (prop1->name, prop2->name))
3853                 return FALSE;
3854
3855         if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3856                 return FALSE;
3857         if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3858                 return FALSE;
3859         return TRUE;
3860 }
3861
3862 static gboolean
3863 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3864 {
3865         if (!accessor)
3866                 return FALSE;
3867
3868         return method_nonpublic (accessor, start_klass);
3869 }
3870
3871 static MonoArray*
3872 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3873 {
3874         MonoDomain *domain; 
3875         static MonoClass *System_Reflection_PropertyInfo;
3876         MonoClass *startklass, *klass;
3877         MonoArray *res;
3878         MonoMethod *method;
3879         MonoProperty *prop;
3880         int i, match;
3881         int len = 0;
3882         guint32 flags;
3883         gchar *propname = NULL;
3884         int (*compare_func) (const char *s1, const char *s2) = NULL;
3885         gpointer iter;
3886         GHashTable *properties;
3887
3888         MONO_ARCH_SAVE_REGS;
3889
3890         if (!System_Reflection_PropertyInfo)
3891                 System_Reflection_PropertyInfo = mono_class_from_name (
3892                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3893
3894         domain = ((MonoObject *)type)->vtable->domain;
3895         if (type->type->byref)
3896                 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3897         klass = startklass = mono_class_from_mono_type (type->type);
3898         if (name != NULL) {
3899                 propname = mono_string_to_utf8 (name);
3900                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3901         }
3902
3903         mono_class_setup_vtable (klass);
3904
3905         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3906         i = 0;
3907         len = 2;
3908         res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3909 handle_parent:
3910         mono_class_setup_vtable (klass);
3911         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3912                 g_hash_table_destroy (properties);
3913                 if (name != NULL)
3914                         g_free (propname);
3915                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3916         }
3917
3918         iter = NULL;
3919         while ((prop = mono_class_get_properties (klass, &iter))) {
3920                 match = 0;
3921                 method = prop->get;
3922                 if (!method)
3923                         method = prop->set;
3924                 if (method)
3925                         flags = method->flags;
3926                 else
3927                         flags = 0;
3928                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3929                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3930                         if (bflags & BFLAGS_Public)
3931                                 match++;
3932                 } else if (bflags & BFLAGS_NonPublic) {
3933                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3934                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3935                                 match++;
3936                         }
3937                 }
3938                 if (!match)
3939                         continue;
3940                 match = 0;
3941                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3942                         if (bflags & BFLAGS_Static)
3943                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3944                                         match++;
3945                 } else {
3946                         if (bflags & BFLAGS_Instance)
3947                                 match++;
3948                 }
3949
3950                 if (!match)
3951                         continue;
3952                 match = 0;
3953
3954                 if (name != NULL) {
3955                         if (compare_func (propname, prop->name))
3956                                 continue;
3957                 }
3958                 
3959                 if (g_hash_table_lookup (properties, prop))
3960                         continue;
3961
3962                 if (i >= len) {
3963                         MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3964                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3965                         len *= 2;
3966                         res = new_res;
3967                 }
3968                 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3969                 ++i;
3970                 
3971                 g_hash_table_insert (properties, prop, prop);
3972         }
3973         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3974                 goto handle_parent;
3975
3976         g_hash_table_destroy (properties);
3977         g_free (propname);
3978         if (i != len) {
3979                 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3980                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3981                 res = new_res;
3982                 /*
3983                  * Better solution for the new GC.
3984                  * res->max_length = i;
3985                  */
3986         }
3987         return res;
3988 }
3989
3990 static MonoReflectionEvent *
3991 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3992 {
3993         MonoDomain *domain;
3994         MonoClass *klass, *startklass;
3995         gpointer iter;
3996         MonoEvent *event;
3997         MonoMethod *method;
3998         gchar *event_name;
3999
4000         MONO_ARCH_SAVE_REGS;
4001
4002         event_name = mono_string_to_utf8 (name);
4003         if (type->type->byref)
4004                 return NULL;
4005         klass = startklass = mono_class_from_mono_type (type->type);
4006         domain = mono_object_domain (type);
4007
4008 handle_parent:  
4009         if (klass->exception_type != MONO_EXCEPTION_NONE)
4010                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4011
4012         iter = NULL;
4013         while ((event = mono_class_get_events (klass, &iter))) {
4014                 if (strcmp (event->name, event_name))
4015                         continue;
4016
4017                 method = event->add;
4018                 if (!method)
4019                         method = event->remove;
4020                 if (!method)
4021                         method = event->raise;
4022                 if (method) {
4023                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4024                                 if (!(bflags & BFLAGS_Public))
4025                                         continue;
4026                         } else {
4027                                 if (!(bflags & BFLAGS_NonPublic))
4028                                         continue;
4029                                 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4030                                         continue;
4031                         }
4032                 }
4033                 else
4034                         if (!(bflags & BFLAGS_NonPublic))
4035                                 continue;
4036
4037                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4038                         if (!(bflags & BFLAGS_Static))
4039                                 continue;
4040                         if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4041                                 continue;
4042                 } else {
4043                         if (!(bflags & BFLAGS_Instance))
4044                                 continue;
4045                 }
4046
4047                 g_free (event_name);
4048                 return mono_event_get_object (domain, startklass, event);
4049         }
4050
4051         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4052                 goto handle_parent;
4053
4054         g_free (event_name);
4055         return NULL;
4056 }
4057
4058 static MonoArray*
4059 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4060 {
4061         MonoDomain *domain; 
4062         static MonoClass *System_Reflection_EventInfo;
4063         MonoClass *startklass, *klass;
4064         MonoArray *res;
4065         MonoMethod *method;
4066         MonoEvent *event;
4067         int i, len, match;
4068         gpointer iter;
4069
4070         MONO_ARCH_SAVE_REGS;
4071
4072         if (!System_Reflection_EventInfo)
4073                 System_Reflection_EventInfo = mono_class_from_name (
4074                         mono_defaults.corlib, "System.Reflection", "EventInfo");
4075
4076         domain = mono_object_domain (type);
4077         if (type->type->byref)
4078                 return mono_array_new (domain, System_Reflection_EventInfo, 0);
4079         klass = startklass = mono_class_from_mono_type (type->type);
4080
4081         i = 0;
4082         len = 2;
4083         res = mono_array_new (domain, System_Reflection_EventInfo, len);
4084 handle_parent:  
4085         if (klass->exception_type != MONO_EXCEPTION_NONE)
4086                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4087
4088         iter = NULL;
4089         while ((event = mono_class_get_events (klass, &iter))) {
4090                 match = 0;
4091                 method = event->add;
4092                 if (!method)
4093                         method = event->remove;
4094                 if (!method)
4095                         method = event->raise;
4096                 if (method) {
4097                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4098                                 if (bflags & BFLAGS_Public)
4099                                         match++;
4100                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4101                                 if (bflags & BFLAGS_NonPublic)
4102                                         match++;
4103                         }
4104                 }
4105                 else
4106                         if (bflags & BFLAGS_NonPublic)
4107                                 match ++;
4108                 if (!match)
4109                         continue;
4110                 match = 0;
4111                 if (method) {
4112                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4113                                 if (bflags & BFLAGS_Static)
4114                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4115                                                 match++;
4116                         } else {
4117                                 if (bflags & BFLAGS_Instance)
4118                                         match++;
4119                         }
4120                 }
4121                 else
4122                         if (bflags & BFLAGS_Instance)
4123                                 match ++;
4124                 if (!match)
4125                         continue;
4126                 match = 0;
4127                 if (i >= len) {
4128                         MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
4129                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
4130                         len *= 2;
4131                         res = new_res;
4132                 }
4133                 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
4134                 ++i;
4135         }
4136         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4137                 goto handle_parent;
4138         if (i != len) {
4139                 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
4140                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4141                 res = new_res;
4142                 /*
4143                  * Better solution for the new GC.
4144                  * res->max_length = i;
4145                  */
4146         }
4147         return res;
4148 }
4149
4150 static MonoReflectionType *
4151 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4152 {
4153         MonoDomain *domain; 
4154         MonoClass *klass;
4155         MonoClass *nested;
4156         char *str;
4157         gpointer iter;
4158         
4159         MONO_ARCH_SAVE_REGS;
4160
4161         domain = ((MonoObject *)type)->vtable->domain;
4162         if (type->type->byref)
4163                 return NULL;
4164         klass = mono_class_from_mono_type (type->type);
4165         str = mono_string_to_utf8 (name);
4166
4167  handle_parent:
4168         if (klass->exception_type != MONO_EXCEPTION_NONE)
4169                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4170
4171         /*
4172          * If a nested type is generic, return its generic type definition.
4173          * Note that this means that the return value is essentially a
4174          * nested type of the generic type definition of @klass.
4175          *
4176          * A note in MSDN claims that a generic type definition can have
4177          * nested types that aren't generic.  In any case, the container of that
4178          * nested type would be the generic type definition.
4179          */
4180         if (klass->generic_class)
4181                 klass = klass->generic_class->container_class;
4182
4183         iter = NULL;
4184         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4185                 int match = 0;
4186                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4187                         if (bflags & BFLAGS_Public)
4188                                 match++;
4189                 } else {
4190                         if (bflags & BFLAGS_NonPublic)
4191                                 match++;
4192                 }
4193                 if (!match)
4194                         continue;
4195                 if (strcmp (nested->name, str) == 0){
4196                         g_free (str);
4197                         return mono_type_get_object (domain, &nested->byval_arg);
4198                 }
4199         }
4200         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4201                 goto handle_parent;
4202         g_free (str);
4203         return NULL;
4204 }
4205
4206 static MonoArray*
4207 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4208 {
4209         MonoDomain *domain; 
4210         MonoClass *klass;
4211         MonoArray *res;
4212         MonoObject *member;
4213         int i, len, match;
4214         MonoClass *nested;
4215         gpointer iter;
4216
4217         MONO_ARCH_SAVE_REGS;
4218
4219         domain = ((MonoObject *)type)->vtable->domain;
4220         if (type->type->byref)
4221                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4222         klass = mono_class_from_mono_type (type->type);
4223         if (klass->exception_type != MONO_EXCEPTION_NONE)
4224                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4225
4226         /*
4227          * If a nested type is generic, return its generic type definition.
4228          * Note that this means that the return value is essentially the set
4229          * of nested types of the generic type definition of @klass.
4230          *
4231          * A note in MSDN claims that a generic type definition can have
4232          * nested types that aren't generic.  In any case, the container of that
4233          * nested type would be the generic type definition.
4234          */
4235         if (klass->generic_class)
4236                 klass = klass->generic_class->container_class;
4237
4238         i = 0;
4239         len = 1;
4240         res = mono_array_new (domain, mono_defaults.monotype_class, len);
4241         iter = NULL;
4242         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4243                 match = 0;
4244                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4245                         if (bflags & BFLAGS_Public)
4246                                 match++;
4247                 } else {
4248                         if (bflags & BFLAGS_NonPublic)
4249                                 match++;
4250                 }
4251                 if (!match)
4252                         continue;
4253                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4254                 if (i >= len) {
4255                         MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
4256                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
4257                         len *= 2;
4258                         res = new_res;
4259                 }
4260                 mono_array_setref (res, i, member);
4261                 ++i;
4262         }
4263         if (i != len) {
4264                 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
4265                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4266                 res = new_res;
4267                 /*
4268                  * Better solution for the new GC.
4269                  * res->max_length = i;
4270                  */
4271         }
4272         return res;
4273 }
4274
4275 static MonoReflectionType*
4276 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4277 {
4278         gchar *str;
4279         MonoType *type = NULL;
4280         MonoTypeNameParse info;
4281         gboolean type_resolve;
4282
4283         MONO_ARCH_SAVE_REGS;
4284
4285         /* On MS.NET, this does not fire a TypeResolve event */
4286         type_resolve = TRUE;
4287         str = mono_string_to_utf8 (name);
4288         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4289         if (!mono_reflection_parse_type (str, &info)) {
4290                 g_free (str);
4291                 mono_reflection_free_type_info (&info);
4292                 if (throwOnError) /* uhm: this is a parse error, though... */
4293                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
4294                 /*g_print ("failed parse\n");*/
4295                 return NULL;
4296         }
4297
4298         if (info.assembly.name) {
4299                 g_free (str);
4300                 mono_reflection_free_type_info (&info);
4301                 if (throwOnError) {
4302                         /* 1.0 and 2.0 throw different exceptions */
4303                         if (mono_defaults.generic_ilist_class)
4304                                 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4305                         else
4306                                 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4307                 }
4308                 return NULL;
4309         }
4310
4311         if (module != NULL) {
4312                 if (module->image)
4313                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4314                 else
4315                         type = NULL;
4316         }
4317         else
4318                 if (assembly->assembly->dynamic) {
4319                         /* Enumerate all modules */
4320                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4321                         int i;
4322
4323                         type = NULL;
4324                         if (abuilder->modules) {
4325                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4326                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4327                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4328                                         if (type)
4329                                                 break;
4330                                 }
4331                         }
4332
4333                         if (!type && abuilder->loaded_modules) {
4334                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4335                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4336                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4337                                         if (type)
4338                                                 break;
4339                                 }
4340                         }
4341                 }
4342                 else
4343                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4344         g_free (str);
4345         mono_reflection_free_type_info (&info);
4346         if (!type) {
4347                 MonoException *e = NULL;
4348                 
4349                 if (throwOnError)
4350                         e = mono_get_exception_type_load (name, NULL);
4351
4352                 mono_loader_clear_error ();
4353
4354                 if (e != NULL)
4355                         mono_raise_exception (e);
4356
4357                 return NULL;
4358         }
4359
4360         if (type->type == MONO_TYPE_CLASS) {
4361                 MonoClass *klass = mono_type_get_class (type);
4362
4363                 if (mono_is_security_manager_active () && !klass->exception_type)
4364                         /* Some security problems are detected during generic vtable construction */
4365                         mono_class_setup_vtable (klass);
4366                 /* need to report exceptions ? */
4367                 if (throwOnError && klass->exception_type) {
4368                         /* report SecurityException (or others) that occured when loading the assembly */
4369                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4370                         mono_loader_clear_error ();
4371                         mono_raise_exception (exc);
4372                 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4373                         return NULL;
4374                 }
4375         }
4376
4377         /* g_print ("got it\n"); */
4378         return mono_type_get_object (mono_object_domain (assembly), type);
4379 }
4380
4381 static MonoString *
4382 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4383 {
4384         MonoDomain *domain = mono_object_domain (assembly); 
4385         MonoAssembly *mass = assembly->assembly;
4386         MonoString *res = NULL;
4387         gchar *uri;
4388         gchar *absolute;
4389         gchar *content;
4390         gchar *shadow_ini_file;
4391         gsize len;
4392         gchar *dirname;
4393         
4394         MONO_ARCH_SAVE_REGS;
4395
4396         if (g_path_is_absolute (mass->image->name)) {
4397                 absolute = g_strdup (mass->image->name);
4398                 dirname = g_path_get_dirname (absolute);
4399         } else {
4400                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4401                 dirname = g_strdup (mass->basedir);
4402         }
4403
4404         /* Check for shadow-copied assembly */
4405         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4406                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4407                 content = NULL;
4408                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4409                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4410                         if (content) {
4411                                 g_free (content);
4412                                 content = NULL;
4413                         }
4414                 }
4415                 g_free (shadow_ini_file);
4416                 if (content != NULL) {
4417                         g_free (absolute);
4418                         absolute = content;
4419                 }
4420         }
4421         g_free (dirname);
4422
4423 #if PLATFORM_WIN32
4424         {
4425                 gint i;
4426                 for (i = strlen (absolute) - 1; i >= 0; i--)
4427                         if (absolute [i] == '\\')
4428                                 absolute [i] = '/';
4429         }
4430 #endif
4431         if (escaped) {
4432                 uri = g_filename_to_uri (absolute, NULL, NULL);
4433         } else {
4434                 const char *prepend = "file://";
4435 #if PLATFORM_WIN32
4436                 if (*absolute == '/' && *(absolute + 1) == '/') {
4437                         prepend = "file:";
4438                 } else {
4439                         prepend = "file:///";
4440                 }
4441 #endif
4442                 uri = g_strconcat (prepend, absolute, NULL);
4443         }
4444
4445         if (uri) {
4446                 res = mono_string_new (domain, uri);
4447                 g_free (uri);
4448         }
4449         g_free (absolute);
4450         return res;
4451 }
4452
4453 static MonoBoolean
4454 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4455 {
4456         MonoAssembly *mass = assembly->assembly;
4457
4458         MONO_ARCH_SAVE_REGS;
4459
4460         return mass->in_gac;
4461 }
4462
4463 static MonoReflectionAssembly*
4464 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4465 {
4466         gchar *name;
4467         MonoAssembly *res;
4468         MonoImageOpenStatus status;
4469         
4470         MONO_ARCH_SAVE_REGS;
4471
4472         name = mono_string_to_utf8 (mname);
4473         res = mono_assembly_load_with_partial_name (name, &status);
4474
4475         g_free (name);
4476
4477         if (res == NULL)
4478                 return NULL;
4479         return mono_assembly_get_object (mono_domain_get (), res);
4480 }
4481
4482 static MonoString *
4483 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4484 {
4485         MonoDomain *domain = mono_object_domain (assembly); 
4486         MonoString *res;
4487
4488         MONO_ARCH_SAVE_REGS;
4489
4490         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4491
4492         return res;
4493 }
4494
4495 static MonoBoolean
4496 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4497 {
4498         MONO_ARCH_SAVE_REGS;
4499
4500         return assembly->assembly->ref_only;
4501 }
4502
4503 static MonoString *
4504 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4505 {
4506         MonoDomain *domain = mono_object_domain (assembly); 
4507
4508         MONO_ARCH_SAVE_REGS;
4509
4510         return mono_string_new (domain, assembly->assembly->image->version);
4511 }
4512
4513 static MonoReflectionMethod*
4514 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4515 {
4516         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4517
4518         MONO_ARCH_SAVE_REGS;
4519
4520         if (!token)
4521                 return NULL;
4522         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4523 }
4524
4525 static MonoReflectionModule*
4526 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4527 {
4528         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4529 }
4530
4531 static MonoArray*
4532 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4533 {
4534         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4535         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4536         int i;
4537         const char *val;
4538
4539         MONO_ARCH_SAVE_REGS;
4540
4541         for (i = 0; i < table->rows; ++i) {
4542                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4543                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4544         }
4545         return result;
4546 }
4547
4548 static MonoObject*
4549 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4550 {
4551         static MonoClass *System_Version = NULL;
4552         static MonoMethod *create_version = NULL;
4553         MonoObject *result;
4554         gpointer args [4];
4555         
4556         if (!System_Version) {
4557                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4558                 g_assert (System_Version);
4559         }
4560
4561         if (!create_version) {
4562                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4563                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4564                 g_assert (create_version);
4565                 mono_method_desc_free (desc);
4566         }
4567
4568         args [0] = &major;
4569         args [1] = &minor;
4570         args [2] = &build;
4571         args [3] = &revision;
4572         result = mono_object_new (domain, System_Version);
4573         mono_runtime_invoke (create_version, result, args, NULL);
4574
4575         return result;
4576 }
4577
4578 static MonoArray*
4579 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4580 {
4581         static MonoClass *System_Reflection_AssemblyName;
4582         MonoArray *result;
4583         MonoDomain *domain = mono_object_domain (assembly);
4584         int i, count = 0;
4585         static MonoMethod *create_culture = NULL;
4586         MonoImage *image = assembly->assembly->image;
4587         MonoTableInfo *t;
4588
4589         MONO_ARCH_SAVE_REGS;
4590
4591         if (!System_Reflection_AssemblyName)
4592                 System_Reflection_AssemblyName = mono_class_from_name (
4593                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4594
4595         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4596         count = t->rows;
4597
4598         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4599
4600         if (count > 0) {
4601                 MonoMethodDesc *desc = mono_method_desc_new (
4602                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4603                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4604                 g_assert (create_culture);
4605                 mono_method_desc_free (desc);
4606         }
4607
4608         for (i = 0; i < count; i++) {
4609                 MonoReflectionAssemblyName *aname;
4610                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4611
4612                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4613
4614                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4615                         domain, System_Reflection_AssemblyName);
4616
4617                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4618
4619                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4620                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4621                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4622                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4623                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4624                 aname->versioncompat = 1; /* SameMachine (default) */
4625                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4626                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4627
4628                 if (create_culture) {
4629                         gpointer args [2];
4630                         MonoBoolean assembly_ref = 1;
4631                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4632                         args [1] = &assembly_ref;
4633                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4634                 }
4635                 
4636                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4637                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4638                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4639
4640                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4641                                 /* public key token isn't copied - the class library will 
4642                                 automatically generate it from the public key if required */
4643                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4644                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4645                         } else {
4646                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4647                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4648                         }
4649                 } else {
4650                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4651                 }
4652                 
4653                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4654                          be used under partial trust as path information isn't present). */
4655
4656                 mono_array_setref (result, i, aname);
4657         }
4658         return result;
4659 }
4660
4661 typedef struct {
4662         MonoArray *res;
4663         int idx;
4664 } NameSpaceInfo;
4665
4666 static void
4667 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4668 {
4669         MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4670
4671         mono_array_setref (info->res, info->idx, name);
4672         info->idx++;
4673 }
4674
4675 static MonoArray*
4676 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
4677 {
4678         MonoImage *img = assembly->assembly->image;
4679         MonoArray *res;
4680         NameSpaceInfo info;
4681
4682         MONO_ARCH_SAVE_REGS;
4683
4684         if (!img->name_cache)
4685                 mono_image_init_name_cache (img);
4686
4687         res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4688         info.res = res;
4689         info.idx = 0;
4690         g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4691
4692         return res;
4693 }
4694
4695 /* move this in some file in mono/util/ */
4696 static char *
4697 g_concat_dir_and_file (const char *dir, const char *file)
4698 {
4699         g_return_val_if_fail (dir != NULL, NULL);
4700         g_return_val_if_fail (file != NULL, NULL);
4701
4702         /*
4703          * If the directory name doesn't have a / on the end, we need
4704          * to add one so we get a proper path to the file
4705          */
4706         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4707                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4708         else
4709                 return g_strconcat (dir, file, NULL);
4710 }
4711
4712 static void *
4713 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4714 {
4715         char *n = mono_string_to_utf8 (name);
4716         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4717         guint32 i;
4718         guint32 cols [MONO_MANIFEST_SIZE];
4719         guint32 impl, file_idx;
4720         const char *val;
4721         MonoImage *module;
4722
4723         MONO_ARCH_SAVE_REGS;
4724
4725         for (i = 0; i < table->rows; ++i) {
4726                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4727                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4728                 if (strcmp (val, n) == 0)
4729                         break;
4730         }
4731         g_free (n);
4732         if (i == table->rows)
4733                 return NULL;
4734         /* FIXME */
4735         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4736         if (impl) {
4737                 /*
4738                  * this code should only be called after obtaining the 
4739                  * ResourceInfo and handling the other cases.
4740                  */
4741                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4742                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4743
4744                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4745                 if (!module)
4746                         return NULL;
4747         }
4748         else
4749                 module = assembly->assembly->image;
4750
4751         *ref_module = mono_module_get_object (mono_domain_get (), module);
4752
4753         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4754 }
4755
4756 static gboolean
4757 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4758 {
4759         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4760         int i;
4761         guint32 cols [MONO_MANIFEST_SIZE];
4762         guint32 file_cols [MONO_FILE_SIZE];
4763         const char *val;
4764         char *n;
4765
4766         MONO_ARCH_SAVE_REGS;
4767
4768         n = mono_string_to_utf8 (name);
4769         for (i = 0; i < table->rows; ++i) {
4770                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4771                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4772                 if (strcmp (val, n) == 0)
4773                         break;
4774         }
4775         g_free (n);
4776         if (i == table->rows)
4777                 return FALSE;
4778
4779         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4780                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4781         }
4782         else {
4783                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4784                 case MONO_IMPLEMENTATION_FILE:
4785                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4786                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4787                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4788                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4789                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4790                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4791                                 info->location = 0;
4792                         else
4793                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4794                         break;
4795
4796                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4797                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4798                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4799                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4800                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4801                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4802                                 g_free (msg);
4803                                 mono_raise_exception (ex);
4804                         }
4805                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4806
4807                         /* Obtain info recursively */
4808                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4809                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4810                         break;
4811
4812                 case MONO_IMPLEMENTATION_EXP_TYPE:
4813                         g_assert_not_reached ();
4814                         break;
4815                 }
4816         }
4817
4818         return TRUE;
4819 }
4820
4821 static MonoObject*
4822 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4823 {
4824         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4825         MonoArray *result = NULL;
4826         int i, count;
4827         const char *val;
4828         char *n;
4829
4830         MONO_ARCH_SAVE_REGS;
4831
4832         /* check hash if needed */
4833         if (name) {
4834                 n = mono_string_to_utf8 (name);
4835                 for (i = 0; i < table->rows; ++i) {
4836                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4837                         if (strcmp (val, n) == 0) {
4838                                 MonoString *fn;
4839                                 g_free (n);
4840                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4841                                 fn = mono_string_new (mono_object_domain (assembly), n);
4842                                 g_free (n);
4843                                 return (MonoObject*)fn;
4844                         }
4845                 }
4846                 g_free (n);
4847                 return NULL;
4848         }
4849
4850         count = 0;
4851         for (i = 0; i < table->rows; ++i) {
4852                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4853                         count ++;
4854         }
4855
4856         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4857
4858         count = 0;
4859         for (i = 0; i < table->rows; ++i) {
4860                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4861                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4862                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4863                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4864                         g_free (n);
4865                         count ++;
4866                 }
4867         }
4868         return (MonoObject*)result;
4869 }
4870
4871 static MonoArray*
4872 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4873 {
4874         MonoDomain *domain = mono_domain_get();
4875         MonoArray *res;
4876         MonoClass *klass;
4877         int i, j, file_count = 0;
4878         MonoImage **modules;
4879         guint32 module_count, real_module_count;
4880         MonoTableInfo *table;
4881         guint32 cols [MONO_FILE_SIZE];
4882         MonoImage *image = assembly->assembly->image;
4883
4884         g_assert (image != NULL);
4885         g_assert (!assembly->assembly->dynamic);
4886
4887         table = &image->tables [MONO_TABLE_FILE];
4888         file_count = table->rows;
4889
4890         modules = image->modules;
4891         module_count = image->module_count;
4892
4893         real_module_count = 0;
4894         for (i = 0; i < module_count; ++i)
4895                 if (modules [i])
4896                         real_module_count ++;
4897
4898         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4899         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4900
4901         mono_array_setref (res, 0, mono_module_get_object (domain, image));
4902         j = 1;
4903         for (i = 0; i < module_count; ++i)
4904                 if (modules [i]) {
4905                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4906                         ++j;
4907                 }
4908
4909         for (i = 0; i < file_count; ++i, ++j) {
4910                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4911                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4912                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4913                 else {
4914                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4915                         if (!m) {
4916                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4917                                 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4918                         }
4919                         mono_array_setref (res, j, mono_module_get_object (domain, m));
4920                 }
4921         }
4922
4923         return res;
4924 }
4925
4926 static MonoReflectionMethod*
4927 ves_icall_GetCurrentMethod (void) 
4928 {
4929         MonoMethod *m = mono_method_get_last_managed ();
4930
4931         MONO_ARCH_SAVE_REGS;
4932
4933         return mono_method_get_object (mono_domain_get (), m, NULL);
4934 }
4935
4936
4937 static MonoMethod*
4938 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4939 {
4940         int offset = -1, i;
4941         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4942                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4943                 //method is inflated, we should inflate it on the other class
4944                 MonoGenericContext ctx;
4945                 ctx.method_inst = inflated->context.method_inst;
4946                 ctx.class_inst = inflated->context.class_inst;
4947                 if (klass->generic_class)
4948                         ctx.class_inst = klass->generic_class->context.class_inst;
4949                 else if (klass->generic_container)
4950                         ctx.class_inst = klass->generic_container->context.class_inst;
4951                 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4952         }
4953
4954         mono_class_setup_methods (method->klass);
4955         for (i = 0; i < method->klass->method.count; ++i) {
4956                 if (method->klass->methods [i] == method) {
4957                         offset = i;
4958                         break;
4959                 }       
4960         }
4961         mono_class_setup_methods (klass);
4962         g_assert (offset >= 0 && offset < klass->method.count);
4963         return klass->methods [offset];
4964 }
4965
4966 static MonoReflectionMethod*
4967 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4968 {
4969         MonoClass *klass;
4970         if (type) {
4971                 klass = mono_class_from_mono_type (type);
4972                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
4973                         return NULL;
4974                 if (method->klass != klass)
4975                         method = mono_method_get_equivalent_method (method, klass);
4976         } else
4977                 klass = method->klass;
4978         return mono_method_get_object (mono_domain_get (), method, klass);
4979 }
4980
4981 static MonoReflectionMethod*
4982 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4983 {
4984         return mono_method_get_object (mono_domain_get (), method, NULL);
4985 }
4986
4987 static MonoReflectionMethodBody*
4988 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4989 {
4990         return mono_method_body_get_object (mono_domain_get (), method);
4991 }
4992
4993 static MonoReflectionAssembly*
4994 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4995 {
4996         MonoMethod *dest = NULL;
4997
4998         MONO_ARCH_SAVE_REGS;
4999
5000         mono_stack_walk_no_il (get_executing, &dest);
5001         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5002 }
5003
5004
5005 static MonoReflectionAssembly*
5006 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5007 {
5008         MonoDomain* domain = mono_domain_get ();
5009
5010         MONO_ARCH_SAVE_REGS;
5011
5012         if (!domain->entry_assembly)
5013                 return NULL;
5014
5015         return mono_assembly_get_object (domain, domain->entry_assembly);
5016 }
5017
5018 static MonoReflectionAssembly*
5019 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5020 {
5021         MonoMethod *m;
5022         MonoMethod *dest;
5023
5024         MONO_ARCH_SAVE_REGS;
5025
5026         dest = NULL;
5027         mono_stack_walk_no_il (get_executing, &dest);
5028         m = dest;
5029         mono_stack_walk_no_il (get_caller, &dest);
5030         if (!dest)
5031                 dest = m;
5032         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5033 }
5034
5035 static MonoString *
5036 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5037                                        gboolean assembly_qualified)
5038 {
5039         MonoDomain *domain = mono_object_domain (object); 
5040         MonoTypeNameFormat format;
5041         MonoString *res;
5042         gchar *name;
5043
5044         MONO_ARCH_SAVE_REGS;
5045         if (full_name)
5046                 format = assembly_qualified ?
5047                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5048                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5049         else
5050                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5051  
5052         name = mono_type_get_name_full (object->type, format);
5053         if (!name)
5054                 return NULL;
5055
5056         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5057                 g_free (name);
5058                 return NULL;
5059         }
5060
5061         res = mono_string_new (domain, name);
5062         g_free (name);
5063
5064         return res;
5065 }
5066
5067 static void
5068 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5069 {
5070         static MonoMethod *create_culture = NULL;
5071         gpointer args [2];
5072         guint32 pkey_len;
5073         const char *pkey_ptr;
5074         gchar *codebase;
5075         MonoBoolean assembly_ref = 0;
5076
5077         MONO_ARCH_SAVE_REGS;
5078
5079         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5080         aname->major = name->major;
5081         aname->minor = name->minor;
5082         aname->build = name->build;
5083         aname->flags = name->flags;
5084         aname->revision = name->revision;
5085         aname->hashalg = name->hash_alg;
5086         aname->versioncompat = 1; /* SameMachine (default) */
5087
5088         if (by_default_version)
5089                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5090
5091         codebase = NULL;
5092         if (absolute != NULL && *absolute != '\0') {
5093                 const gchar *prepend = "file://";
5094                 gchar *result;
5095
5096                 codebase = g_strdup (absolute);
5097
5098 #if PLATFORM_WIN32
5099                 {
5100                         gint i;
5101                         for (i = strlen (codebase) - 1; i >= 0; i--)
5102                                 if (codebase [i] == '\\')
5103                                         codebase [i] = '/';
5104
5105                         if (*codebase == '/' && *(codebase + 1) == '/') {
5106                                 prepend = "file:";
5107                         } else {
5108                                 prepend = "file:///";
5109                         }
5110                 }
5111 #endif
5112                 result = g_strconcat (prepend, codebase, NULL);
5113                 g_free (codebase);
5114                 codebase = result;
5115         }
5116
5117         if (codebase) {
5118                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5119                 g_free (codebase);
5120         }
5121
5122         if (!create_culture) {
5123                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5124                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5125                 g_assert (create_culture);
5126                 mono_method_desc_free (desc);
5127         }
5128
5129         if (name->culture) {
5130                 args [0] = mono_string_new (domain, name->culture);
5131                 args [1] = &assembly_ref;
5132                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5133         }
5134
5135         if (name->public_key) {
5136                 pkey_ptr = (char*)name->public_key;
5137                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5138
5139                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5140                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5141                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5142         } else if (default_publickey) {
5143                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5144                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5145         }
5146
5147         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5148         if (name->public_key_token [0]) {
5149                 int i, j;
5150                 char *p;
5151
5152                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5153                 p = mono_array_addr (aname->keyToken, char, 0);
5154
5155                 for (i = 0, j = 0; i < 8; i++) {
5156                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5157                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5158                         p++;
5159                 }
5160         } else if (default_token) {
5161                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5162         }
5163 }
5164
5165 static MonoString *
5166 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5167 {
5168         MonoDomain *domain = mono_object_domain (assembly); 
5169         MonoAssembly *mass = assembly->assembly;
5170         MonoString *res;
5171         gchar *name;
5172
5173         name = g_strdup_printf (
5174                 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5175                 mass->aname.name,
5176                 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5177                 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5178                 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5179                 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5180
5181         res = mono_string_new (domain, name);
5182         g_free (name);
5183
5184         return res;
5185 }
5186
5187 static void
5188 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5189 {
5190         gchar *absolute;
5191         MonoAssembly *mass = assembly->assembly;
5192
5193         MONO_ARCH_SAVE_REGS;
5194
5195         if (g_path_is_absolute (mass->image->name)) {
5196                 fill_reflection_assembly_name (mono_object_domain (assembly),
5197                         aname, &mass->aname, mass->image->name, TRUE,
5198                         TRUE, mono_framework_version () >= 2);
5199                 return;
5200         }
5201         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5202
5203         fill_reflection_assembly_name (mono_object_domain (assembly),
5204                 aname, &mass->aname, absolute, TRUE, TRUE,
5205                 mono_framework_version () >= 2);
5206
5207         g_free (absolute);
5208 }
5209
5210 static void
5211 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5212 {
5213         char *filename;
5214         MonoImageOpenStatus status = MONO_IMAGE_OK;
5215         gboolean res;
5216         MonoImage *image;
5217         MonoAssemblyName name;
5218
5219         MONO_ARCH_SAVE_REGS;
5220
5221         filename = mono_string_to_utf8 (fname);
5222
5223         image = mono_image_open (filename, &status);
5224
5225         if (!image){
5226                 MonoException *exc;
5227
5228                 g_free (filename);
5229                 if (status == MONO_IMAGE_IMAGE_INVALID)
5230                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5231                 else
5232                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5233                 mono_raise_exception (exc);
5234         }
5235
5236         res = mono_assembly_fill_assembly_name (image, &name);
5237         if (!res) {
5238                 mono_image_close (image);
5239                 g_free (filename);
5240                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5241         }
5242
5243         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5244                 TRUE, mono_framework_version () == 1,
5245                 mono_framework_version () >= 2);
5246
5247         g_free (filename);
5248         mono_image_close (image);
5249 }
5250
5251 static MonoBoolean
5252 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5253         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5254 {
5255         MonoBoolean result = FALSE;
5256         MonoDeclSecurityEntry entry;
5257
5258         /* SecurityAction.RequestMinimum */
5259         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5260                 *minimum = entry.blob;
5261                 *minLength = entry.size;
5262                 result = TRUE;
5263         }
5264         /* SecurityAction.RequestOptional */
5265         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5266                 *optional = entry.blob;
5267                 *optLength = entry.size;
5268                 result = TRUE;
5269         }
5270         /* SecurityAction.RequestRefuse */
5271         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5272                 *refused = entry.blob;
5273                 *refLength = entry.size;
5274                 result = TRUE;
5275         }
5276
5277         return result;  
5278 }
5279
5280 static MonoArray*
5281 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5282 {
5283         MonoArray *res;
5284         MonoClass *klass;
5285         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5286         int i, count;
5287         guint32 attrs, visibility;
5288
5289         /* we start the count from 1 because we skip the special type <Module> */
5290         if (exportedOnly) {
5291                 count = 0;
5292                 for (i = 1; i < tdef->rows; ++i) {
5293                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5294                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5295                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5296                                 count++;
5297                 }
5298         } else {
5299                 count = tdef->rows - 1;
5300         }
5301         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5302         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5303         count = 0;
5304         for (i = 1; i < tdef->rows; ++i) {
5305                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5306                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5307                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5308                         klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5309                         if (klass) {
5310                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5311                         } else {
5312                                 MonoLoaderError *error;
5313                                 MonoException *ex;
5314                                 
5315                                 error = mono_loader_get_last_error ();
5316                                 g_assert (error != NULL);
5317         
5318                                 ex = mono_loader_error_prepare_exception (error);
5319                                 mono_array_setref (*exceptions, count, ex);
5320                         }
5321                         if (mono_loader_get_last_error ())
5322                                 mono_loader_clear_error ();
5323                         count++;
5324                 }
5325         }
5326         
5327         return res;
5328 }
5329
5330 static MonoArray*
5331 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5332 {
5333         MonoArray *res = NULL;
5334         MonoArray *exceptions = NULL;
5335         MonoImage *image = NULL;
5336         MonoTableInfo *table = NULL;
5337         MonoDomain *domain;
5338         GList *list = NULL;
5339         int i, len, ex_count;
5340
5341         MONO_ARCH_SAVE_REGS;
5342
5343         domain = mono_object_domain (assembly);
5344
5345         g_assert (!assembly->assembly->dynamic);
5346         image = assembly->assembly->image;
5347         table = &image->tables [MONO_TABLE_FILE];
5348         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5349
5350         /* Append data from all modules in the assembly */
5351         for (i = 0; i < table->rows; ++i) {
5352                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5353                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5354                         if (loaded_image) {
5355                                 MonoArray *ex2;
5356                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5357                                 /* Append the new types to the end of the array */
5358                                 if (mono_array_length (res2) > 0) {
5359                                         guint32 len1, len2;
5360                                         MonoArray *res3, *ex3;
5361
5362                                         len1 = mono_array_length (res);
5363                                         len2 = mono_array_length (res2);
5364
5365                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5366                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5367                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5368                                         res = res3;
5369
5370                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5371                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5372                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5373                                         exceptions = ex3;
5374                                 }
5375                         }
5376                 }
5377         }
5378
5379         /* the ReflectionTypeLoadException must have all the types (Types property), 
5380          * NULL replacing types which throws an exception. The LoaderException must
5381          * contain all exceptions for NULL items.
5382          */
5383
5384         len = mono_array_length (res);
5385
5386         ex_count = 0;
5387         for (i = 0; i < len; i++) {
5388                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5389                 MonoClass *klass;
5390
5391                 if (t) {
5392                         klass = mono_type_get_class (t->type);
5393                         if ((klass != NULL) && klass->exception_type) {
5394                                 /* keep the class in the list */
5395                                 list = g_list_append (list, klass);
5396                                 /* and replace Type with NULL */
5397                                 mono_array_setref (res, i, NULL);
5398                         }
5399                 } else {
5400                         ex_count ++;
5401                 }
5402         }
5403
5404         if (list || ex_count) {
5405                 GList *tmp = NULL;
5406                 MonoException *exc = NULL;
5407                 MonoArray *exl = NULL;
5408                 int j, length = g_list_length (list) + ex_count;
5409
5410                 mono_loader_clear_error ();
5411
5412                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5413                 /* Types for which mono_class_get () succeeded */
5414                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5415                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5416                         mono_array_setref (exl, i, exc);
5417                 }
5418                 /* Types for which it don't */
5419                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5420                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5421                         if (exc) {
5422                                 g_assert (i < length);
5423                                 mono_array_setref (exl, i, exc);
5424                                 i ++;
5425                         }
5426                 }
5427                 g_list_free (list);
5428                 list = NULL;
5429
5430                 exc = mono_get_exception_reflection_type_load (res, exl);
5431                 mono_loader_clear_error ();
5432                 mono_raise_exception (exc);
5433         }
5434                 
5435         return res;
5436 }
5437
5438 static gboolean
5439 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5440 {
5441         MonoAssemblyName aname;
5442         MonoDomain *domain = mono_object_domain (name);
5443         char *val;
5444         gboolean is_version_defined;
5445         gboolean is_token_defined;
5446
5447         aname.public_key = NULL;
5448         val = mono_string_to_utf8 (assname);
5449         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5450                 g_free ((guint8*) aname.public_key);
5451                 g_free (val);
5452                 return FALSE;
5453         }
5454         
5455         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5456                 FALSE, is_token_defined);
5457
5458         mono_assembly_name_free (&aname);
5459         g_free ((guint8*) aname.public_key);
5460         g_free (val);
5461
5462         return TRUE;
5463 }
5464
5465 static MonoReflectionType*
5466 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5467 {
5468         MonoDomain *domain = mono_object_domain (module); 
5469         MonoClass *klass;
5470
5471         MONO_ARCH_SAVE_REGS;
5472
5473         g_assert (module->image);
5474
5475         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5476                 /* These images do not have a global type */
5477                 return NULL;
5478
5479         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5480         return mono_type_get_object (domain, &klass->byval_arg);
5481 }
5482
5483 static void
5484 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5485 {
5486         /*if (module->image)
5487                 mono_image_close (module->image);*/
5488 }
5489
5490 static MonoString*
5491 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5492 {
5493         MonoDomain *domain = mono_object_domain (module); 
5494
5495         MONO_ARCH_SAVE_REGS;
5496
5497         g_assert (module->image);
5498         return mono_string_new (domain, module->image->guid);
5499 }
5500
5501 static gpointer
5502 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5503 {
5504 #ifdef PLATFORM_WIN32
5505         if (module->image && module->image->is_module_handle)
5506                 return module->image->raw_data;
5507 #endif
5508
5509         return (gpointer) (-1);
5510 }
5511
5512 static void
5513 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5514 {
5515         if (image->dynamic) {
5516                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5517                 *pe_kind = dyn->pe_kind;
5518                 *machine = dyn->machine;
5519         }
5520         else {
5521                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5522                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5523         }
5524 }
5525
5526 static gint32
5527 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5528 {
5529         return (image->md_version_major << 16) | (image->md_version_minor);
5530 }
5531
5532 static MonoArray*
5533 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5534 {
5535         MonoArray *exceptions;
5536         int i;
5537
5538         MONO_ARCH_SAVE_REGS;
5539
5540         if (!module->image)
5541                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5542         else {
5543                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5544                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5545                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5546                         if (ex)
5547                                 mono_raise_exception (ex);
5548                 }
5549                 return res;
5550         }
5551 }
5552
5553 static gboolean
5554 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5555 {
5556         guint32 cols [MONO_MEMBERREF_SIZE];
5557         const char *sig;
5558         mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5559         sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5560         mono_metadata_decode_blob_size (sig, &sig);
5561         return (*sig != 0x6);
5562 }
5563
5564 static void
5565 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5566 {
5567         if (type_args)
5568                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5569                                                                       mono_array_addr (type_args, MonoType*, 0));
5570         else
5571                 context->class_inst = NULL;
5572         if (method_args)
5573                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5574                                                                        mono_array_addr (method_args, MonoType*, 0));
5575         else
5576                 context->method_inst = NULL;
5577 }
5578
5579 static MonoType*
5580 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5581 {
5582         MonoClass *klass;
5583         int table = mono_metadata_token_table (token);
5584         int index = mono_metadata_token_index (token);
5585         MonoGenericContext context;
5586
5587         *error = ResolveTokenError_Other;
5588
5589         /* Validate token */
5590         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5591                 (table != MONO_TABLE_TYPESPEC)) {
5592                 *error = ResolveTokenError_BadTable;
5593                 return NULL;
5594         }
5595
5596         if (image->dynamic) {
5597                 if (type_args || method_args)
5598                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5599                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5600                 if (!klass)
5601                         return NULL;
5602                 return &klass->byval_arg;
5603         }
5604
5605         if ((index <= 0) || (index > image->tables [table].rows)) {
5606                 *error = ResolveTokenError_OutOfRange;
5607                 return NULL;
5608         }
5609
5610         init_generic_context_from_args (&context, type_args, method_args);
5611         klass = mono_class_get_full (image, token, &context);
5612
5613         if (mono_loader_get_last_error ())
5614                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5615
5616         if (klass)
5617                 return &klass->byval_arg;
5618         else
5619                 return NULL;
5620 }
5621
5622 static MonoMethod*
5623 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5624 {
5625         int table = mono_metadata_token_table (token);
5626         int index = mono_metadata_token_index (token);
5627         MonoGenericContext context;
5628         MonoMethod *method;
5629
5630         *error = ResolveTokenError_Other;
5631
5632         /* Validate token */
5633         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5634                 (table != MONO_TABLE_MEMBERREF)) {
5635                 *error = ResolveTokenError_BadTable;
5636                 return NULL;
5637         }
5638
5639         if (image->dynamic) {
5640                 if (type_args || method_args)
5641                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5642                 /* FIXME: validate memberref token type */
5643                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5644         }
5645
5646         if ((index <= 0) || (index > image->tables [table].rows)) {
5647                 *error = ResolveTokenError_OutOfRange;
5648                 return NULL;
5649         }
5650         if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5651                 *error = ResolveTokenError_BadTable;
5652                 return NULL;
5653         }
5654
5655         init_generic_context_from_args (&context, type_args, method_args);
5656         method = mono_get_method_full (image, token, NULL, &context);
5657
5658         if (mono_loader_get_last_error ())
5659                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5660
5661         return method;
5662 }
5663
5664 static MonoString*
5665 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5666 {
5667         int index = mono_metadata_token_index (token);
5668
5669         *error = ResolveTokenError_Other;
5670
5671         /* Validate token */
5672         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5673                 *error = ResolveTokenError_BadTable;
5674                 return NULL;
5675         }
5676
5677         if (image->dynamic)
5678                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5679
5680         if ((index <= 0) || (index >= image->heap_us.size)) {
5681                 *error = ResolveTokenError_OutOfRange;
5682                 return NULL;
5683         }
5684
5685         /* FIXME: What to do if the index points into the middle of a string ? */
5686
5687         return mono_ldstr (mono_domain_get (), image, index);
5688 }
5689
5690 static MonoClassField*
5691 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5692 {
5693         MonoClass *klass;
5694         int table = mono_metadata_token_table (token);
5695         int index = mono_metadata_token_index (token);
5696         MonoGenericContext context;
5697         MonoClassField *field;
5698
5699         *error = ResolveTokenError_Other;
5700
5701         /* Validate token */
5702         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5703                 *error = ResolveTokenError_BadTable;
5704                 return NULL;
5705         }
5706
5707         if (image->dynamic) {
5708                 if (type_args || method_args)
5709                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5710                 /* FIXME: validate memberref token type */
5711                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5712         }
5713
5714         if ((index <= 0) || (index > image->tables [table].rows)) {
5715                 *error = ResolveTokenError_OutOfRange;
5716                 return NULL;
5717         }
5718         if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5719                 *error = ResolveTokenError_BadTable;
5720                 return NULL;
5721         }
5722
5723         init_generic_context_from_args (&context, type_args, method_args);
5724         field = mono_field_from_token (image, token, &klass, &context);
5725
5726         if (mono_loader_get_last_error ())
5727                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5728         
5729         return field;
5730 }
5731
5732
5733 static MonoObject*
5734 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5735 {
5736         int table = mono_metadata_token_table (token);
5737
5738         *error = ResolveTokenError_Other;
5739
5740         switch (table) {
5741         case MONO_TABLE_TYPEDEF:
5742         case MONO_TABLE_TYPEREF:
5743         case MONO_TABLE_TYPESPEC: {
5744                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5745                 if (t)
5746                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5747                 else
5748                         return NULL;
5749         }
5750         case MONO_TABLE_METHOD:
5751         case MONO_TABLE_METHODSPEC: {
5752                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5753                 if (m)
5754                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5755                 else
5756                         return NULL;
5757         }               
5758         case MONO_TABLE_FIELD: {
5759                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5760                 if (f)
5761                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5762                 else
5763                         return NULL;
5764         }
5765         case MONO_TABLE_MEMBERREF:
5766                 if (mono_metadata_memberref_is_method (image, token)) {
5767                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5768                         if (m)
5769                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5770                         else
5771                                 return NULL;
5772                 }
5773                 else {
5774                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5775                         if (f)
5776                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5777                         else
5778                                 return NULL;
5779                 }
5780                 break;
5781
5782         default:
5783                 *error = ResolveTokenError_BadTable;
5784         }
5785
5786         return NULL;
5787 }
5788
5789 static MonoArray*
5790 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5791 {
5792         int table = mono_metadata_token_table (token);
5793         int idx = mono_metadata_token_index (token);
5794         MonoTableInfo *tables = image->tables;
5795         guint32 sig, len;
5796         const char *ptr;
5797         MonoArray *res;
5798
5799         *error = ResolveTokenError_OutOfRange;
5800
5801         /* FIXME: Support other tables ? */
5802         if (table != MONO_TABLE_STANDALONESIG)
5803                 return NULL;
5804
5805         if (image->dynamic)
5806                 return NULL;
5807
5808         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5809                 return NULL;
5810
5811         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5812
5813         ptr = mono_metadata_blob_heap (image, sig);
5814         len = mono_metadata_decode_blob_size (ptr, &ptr);
5815
5816         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5817         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5818         return res;
5819 }
5820
5821 static MonoReflectionType*
5822 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5823 {
5824         MonoClass *klass;
5825         int isbyref = 0, rank;
5826         char *str = mono_string_to_utf8 (smodifiers);
5827         char *p;
5828
5829         MONO_ARCH_SAVE_REGS;
5830
5831         klass = mono_class_from_mono_type (tb->type.type);
5832         p = str;
5833         /* logic taken from mono_reflection_parse_type(): keep in sync */
5834         while (*p) {
5835                 switch (*p) {
5836                 case '&':
5837                         if (isbyref) { /* only one level allowed by the spec */
5838                                 g_free (str);
5839                                 return NULL;
5840                         }
5841                         isbyref = 1;
5842                         p++;
5843                         g_free (str);
5844                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5845                         break;
5846                 case '*':
5847                         klass = mono_ptr_class_get (&klass->byval_arg);
5848                         mono_class_init (klass);
5849                         p++;
5850                         break;
5851                 case '[':
5852                         rank = 1;
5853                         p++;
5854                         while (*p) {
5855                                 if (*p == ']')
5856                                         break;
5857                                 if (*p == ',')
5858                                         rank++;
5859                                 else if (*p != '*') { /* '*' means unknown lower bound */
5860                                         g_free (str);
5861                                         return NULL;
5862                                 }
5863                                 ++p;
5864                         }
5865                         if (*p != ']') {
5866                                 g_free (str);
5867                                 return NULL;
5868                         }
5869                         p++;
5870                         klass = mono_array_class_get (klass, rank);
5871                         mono_class_init (klass);
5872                         break;
5873                 default:
5874                         break;
5875                 }
5876         }
5877         g_free (str);
5878         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5879 }
5880
5881 static MonoBoolean
5882 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5883 {
5884         MonoType *type;
5885         MonoBoolean res;
5886
5887         MONO_ARCH_SAVE_REGS;
5888
5889         type = t->type;
5890         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5891
5892         return res;
5893 }
5894
5895 static MonoReflectionType *
5896 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5897 {
5898         MonoClass *klass, *aklass;
5899
5900         MONO_ARCH_SAVE_REGS;
5901
5902         klass = mono_class_from_mono_type (type->type);
5903         aklass = mono_array_class_get (klass, rank);
5904
5905         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5906 }
5907
5908 static MonoReflectionType *
5909 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5910 {
5911         MonoClass *klass;
5912
5913         MONO_ARCH_SAVE_REGS;
5914
5915         klass = mono_class_from_mono_type (type->type);
5916
5917         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5918 }
5919
5920 static MonoReflectionType *
5921 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5922 {
5923         MonoClass *pklass;
5924
5925         MONO_ARCH_SAVE_REGS;
5926
5927         pklass = mono_ptr_class_get (type->type);
5928
5929         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5930 }
5931
5932 static MonoObject *
5933 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5934                                                    MonoReflectionMethod *info)
5935 {
5936         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5937         MonoObject *delegate;
5938         gpointer func;
5939         MonoMethod *method = info->method;
5940
5941         MONO_ARCH_SAVE_REGS;
5942
5943         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5944
5945         /* FIME: We must check if target is visible to the caller under coreclr.
5946          * The check should be disabled otherwise as it shouldn't raise expection under fulltrust.
5947          */
5948
5949         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5950
5951         if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
5952                 method = mono_marshal_get_static_rgctx_invoke (method);
5953                 func = mono_compile_method (method);
5954         } else if (method->dynamic) {
5955                 /* Creating a trampoline would leak memory */
5956                 func = mono_compile_method (method);
5957         } else {
5958                 func = mono_create_ftnptr (mono_domain_get (),
5959                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5960         }
5961
5962         mono_delegate_ctor_with_method (delegate, target, func, method);
5963
5964         return delegate;
5965 }
5966
5967 static void
5968 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5969 {
5970         /* Reset the invoke impl to the default one */
5971         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5972 }
5973
5974 /*
5975  * Magic number to convert a time which is relative to
5976  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5977  */
5978 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5979
5980 /*
5981  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5982  */
5983 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5984
5985 #ifdef PLATFORM_WIN32
5986 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5987 static void
5988 convert_to_absolute_date(SYSTEMTIME *date)
5989 {
5990 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5991         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5992         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5993         /* from the calendar FAQ */
5994         int a = (14 - date->wMonth) / 12;
5995         int y = date->wYear - a;
5996         int m = date->wMonth + 12 * a - 2;
5997         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5998
5999         /* d is now the day of the week for the first of the month (0 == Sunday) */
6000
6001         int day_of_week = date->wDayOfWeek;
6002
6003         /* set day_in_month to the first day in the month which falls on day_of_week */    
6004         int day_in_month = 1 + (day_of_week - d);
6005         if (day_in_month <= 0)
6006                 day_in_month += 7;
6007
6008         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6009         date->wDay = day_in_month + (date->wDay - 1) * 7;
6010         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6011                 date->wDay -= 7;
6012 }
6013 #endif
6014
6015 #ifndef PLATFORM_WIN32
6016 /*
6017  * Return's the offset from GMT of a local time.
6018  * 
6019  *  tm is a local time
6020  *  t  is the same local time as seconds.
6021  */
6022 static int 
6023 gmt_offset(struct tm *tm, time_t t)
6024 {
6025 #if defined (HAVE_TM_GMTOFF)
6026         return tm->tm_gmtoff;
6027 #else
6028         struct tm g;
6029         time_t t2;
6030         g = *gmtime(&t);
6031         g.tm_isdst = tm->tm_isdst;
6032         t2 = mktime(&g);
6033         return (int)difftime(t, t2);
6034 #endif
6035 }
6036 #endif
6037 /*
6038  * This is heavily based on zdump.c from glibc 2.2.
6039  *
6040  *  * data[0]:  start of daylight saving time (in DateTime ticks).
6041  *  * data[1]:  end of daylight saving time (in DateTime ticks).
6042  *  * data[2]:  utcoffset (in TimeSpan ticks).
6043  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
6044  *  * name[0]:  name of this timezone when not daylight saving.
6045  *  * name[1]:  name of this timezone when daylight saving.
6046  *
6047  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6048  *         the class library allows years between 1 and 9999.
6049  *
6050  *  Returns true on success and zero on failure.
6051  */
6052 static guint32
6053 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6054 {
6055 #ifndef PLATFORM_WIN32
6056         MonoDomain *domain = mono_domain_get ();
6057         struct tm start, tt;
6058         time_t t;
6059
6060         long int gmtoff;
6061         int is_daylight = 0, day;
6062         char tzone [64];
6063
6064         MONO_ARCH_SAVE_REGS;
6065
6066         MONO_CHECK_ARG_NULL (data);
6067         MONO_CHECK_ARG_NULL (names);
6068
6069         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6070         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6071
6072         /* 
6073          * no info is better than crashing: we'll need our own tz data
6074          * to make this work properly, anyway. The range is probably
6075          * reduced to 1970 .. 2037 because that is what mktime is
6076          * guaranteed to support (we get into an infinite loop
6077          * otherwise).
6078          */
6079
6080         memset (&start, 0, sizeof (start));
6081
6082         start.tm_mday = 1;
6083         start.tm_year = year-1900;
6084
6085         t = mktime (&start);
6086
6087         if ((year < 1970) || (year > 2037) || (t == -1)) {
6088                 t = time (NULL);
6089                 tt = *localtime (&t);
6090                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6091                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6092                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6093                 return 1;
6094         }
6095
6096         gmtoff = gmt_offset (&start, t);
6097
6098         /* For each day of the year, calculate the tm_gmtoff. */
6099         for (day = 0; day < 365; day++) {
6100
6101                 t += 3600*24;
6102                 tt = *localtime (&t);
6103
6104                 /* Daylight saving starts or ends here. */
6105                 if (gmt_offset (&tt, t) != gmtoff) {
6106                         struct tm tt1;
6107                         time_t t1;
6108
6109                         /* Try to find the exact hour when daylight saving starts/ends. */
6110                         t1 = t;
6111                         do {
6112                                 t1 -= 3600;
6113                                 tt1 = *localtime (&t1);
6114                         } while (gmt_offset (&tt1, t1) != gmtoff);
6115
6116                         /* Try to find the exact minute when daylight saving starts/ends. */
6117                         do {
6118                                 t1 += 60;
6119                                 tt1 = *localtime (&t1);
6120                         } while (gmt_offset (&tt1, t1) == gmtoff);
6121                         t1+=gmtoff;
6122                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6123                         
6124                         /* Write data, if we're already in daylight saving, we're done. */
6125                         if (is_daylight) {
6126                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6127                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6128                                 return 1;
6129                         } else {
6130                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6131                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6132                                 is_daylight = 1;
6133                         }
6134
6135                         /* This is only set once when we enter daylight saving. */
6136                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6137                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6138
6139                         gmtoff = gmt_offset (&tt, t);
6140                 }
6141         }
6142
6143         if (!is_daylight) {
6144                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6145                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6146                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6147                 mono_array_set ((*data), gint64, 0, 0);
6148                 mono_array_set ((*data), gint64, 1, 0);
6149                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6150                 mono_array_set ((*data), gint64, 3, 0);
6151         }
6152
6153         return 1;
6154 #else
6155         MonoDomain *domain = mono_domain_get ();
6156         TIME_ZONE_INFORMATION tz_info;
6157         FILETIME ft;
6158         int i;
6159         int err, tz_id;
6160
6161         tz_id = GetTimeZoneInformation (&tz_info);
6162         if (tz_id == TIME_ZONE_ID_INVALID)
6163                 return 0;
6164
6165         MONO_CHECK_ARG_NULL (data);
6166         MONO_CHECK_ARG_NULL (names);
6167
6168         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6169         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6170
6171         for (i = 0; i < 32; ++i)
6172                 if (!tz_info.DaylightName [i])
6173                         break;
6174         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6175         for (i = 0; i < 32; ++i)
6176                 if (!tz_info.StandardName [i])
6177                         break;
6178         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6179
6180         if ((year <= 1601) || (year > 30827)) {
6181                 /*
6182                  * According to MSDN, the MS time functions can't handle dates outside
6183                  * this interval.
6184                  */
6185                 return 1;
6186         }
6187
6188         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6189         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6190                 tz_info.StandardDate.wYear = year;
6191                 convert_to_absolute_date(&tz_info.StandardDate);
6192                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6193                 //g_assert(err);
6194                 if (err == 0)
6195                         return 0;
6196                 
6197                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6198                 tz_info.DaylightDate.wYear = year;
6199                 convert_to_absolute_date(&tz_info.DaylightDate);
6200                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6201                 //g_assert(err);
6202                 if (err == 0)
6203                         return 0;
6204                 
6205                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6206         }
6207         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6208         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6209
6210         return 1;
6211 #endif
6212 }
6213
6214 static gpointer
6215 ves_icall_System_Object_obj_address (MonoObject *this) 
6216 {
6217         MONO_ARCH_SAVE_REGS;
6218
6219         return this;
6220 }
6221
6222 /* System.Buffer */
6223
6224 static inline gint32 
6225 mono_array_get_byte_length (MonoArray *array)
6226 {
6227         MonoClass *klass;
6228         int length;
6229         int i;
6230
6231         klass = array->obj.vtable->klass;
6232
6233         if (array->bounds == NULL)
6234                 length = array->max_length;
6235         else {
6236                 length = 1;
6237                 for (i = 0; i < klass->rank; ++ i)
6238                         length *= array->bounds [i].length;
6239         }
6240
6241         switch (klass->element_class->byval_arg.type) {
6242         case MONO_TYPE_I1:
6243         case MONO_TYPE_U1:
6244         case MONO_TYPE_BOOLEAN:
6245                 return length;
6246         case MONO_TYPE_I2:
6247         case MONO_TYPE_U2:
6248         case MONO_TYPE_CHAR:
6249                 return length << 1;
6250         case MONO_TYPE_I4:
6251         case MONO_TYPE_U4:
6252         case MONO_TYPE_R4:
6253                 return length << 2;
6254         case MONO_TYPE_I:
6255         case MONO_TYPE_U:
6256                 return length * sizeof (gpointer);
6257         case MONO_TYPE_I8:
6258         case MONO_TYPE_U8:
6259         case MONO_TYPE_R8:
6260                 return length << 3;
6261         default:
6262                 return -1;
6263         }
6264 }
6265
6266 static gint32 
6267 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6268 {
6269         MONO_ARCH_SAVE_REGS;
6270
6271         return mono_array_get_byte_length (array);
6272 }
6273
6274 static gint8 
6275 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6276 {
6277         MONO_ARCH_SAVE_REGS;
6278
6279         return mono_array_get (array, gint8, idx);
6280 }
6281
6282 static void 
6283 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6284 {
6285         MONO_ARCH_SAVE_REGS;
6286
6287         mono_array_set (array, gint8, idx, value);
6288 }
6289
6290 static MonoBoolean
6291 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6292 {
6293         guint8 *src_buf, *dest_buf;
6294
6295         MONO_ARCH_SAVE_REGS;
6296
6297         /* watch out for integer overflow */
6298         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6299                 return FALSE;
6300
6301         src_buf = (guint8 *)src->vector + src_offset;
6302         dest_buf = (guint8 *)dest->vector + dest_offset;
6303
6304         if (src != dest)
6305                 memcpy (dest_buf, src_buf, count);
6306         else
6307                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6308
6309         return TRUE;
6310 }
6311
6312 static MonoObject *
6313 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6314 {
6315         MonoDomain *domain = mono_object_domain (this); 
6316         MonoObject *res;
6317         MonoRealProxy *rp = ((MonoRealProxy *)this);
6318         MonoTransparentProxy *tp;
6319         MonoType *type;
6320         MonoClass *klass;
6321
6322         MONO_ARCH_SAVE_REGS;
6323
6324         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6325         tp = (MonoTransparentProxy*) res;
6326         
6327         MONO_OBJECT_SETREF (tp, rp, rp);
6328         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6329         klass = mono_class_from_mono_type (type);
6330
6331         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6332         tp->remote_class = mono_remote_class (domain, class_name, klass);
6333
6334         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6335         return res;
6336 }
6337
6338 static MonoReflectionType *
6339 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6340 {
6341         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6342 }
6343
6344 /* System.Environment */
6345
6346 static MonoString *
6347 ves_icall_System_Environment_get_MachineName (void)
6348 {
6349 #if defined (PLATFORM_WIN32)
6350         gunichar2 *buf;
6351         guint32 len;
6352         MonoString *result;
6353
6354         len = MAX_COMPUTERNAME_LENGTH + 1;
6355         buf = g_new (gunichar2, len);
6356
6357         result = NULL;
6358         if (GetComputerName (buf, (PDWORD) &len))
6359                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6360
6361         g_free (buf);
6362         return result;
6363 #elif !defined(DISABLE_SOCKETS)
6364         gchar buf [256];
6365         MonoString *result;
6366
6367         if (gethostname (buf, sizeof (buf)) == 0)
6368                 result = mono_string_new (mono_domain_get (), buf);
6369         else
6370                 result = NULL;
6371         
6372         return result;
6373 #else
6374         return mono_string_new (mono_domain_get (), "mono");
6375 #endif
6376 }
6377
6378 static int
6379 ves_icall_System_Environment_get_Platform (void)
6380 {
6381 #if defined (PLATFORM_WIN32)
6382         /* Win32NT */
6383         return 2;
6384 #elif defined(__MACH__)
6385         /* OSX */
6386         if (mono_framework_version () < 2)
6387                 return 128;
6388
6389         //
6390         // For compatibility with our client code, this will be 4 for a while.
6391         // We will eventually move to 6 to match .NET, but it requires all client
6392         // code to be updated and the documentation everywhere to be updated 
6393         // first.
6394         //
6395         return 4;
6396 #else
6397         /* Unix */
6398         if (mono_framework_version () < 2)
6399                 return 128;
6400         return 4;
6401 #endif
6402 }
6403
6404 static MonoString *
6405 ves_icall_System_Environment_get_NewLine (void)
6406 {
6407         MONO_ARCH_SAVE_REGS;
6408
6409 #if defined (PLATFORM_WIN32)
6410         return mono_string_new (mono_domain_get (), "\r\n");
6411 #else
6412         return mono_string_new (mono_domain_get (), "\n");
6413 #endif
6414 }
6415
6416 static MonoString *
6417 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6418 {
6419         const gchar *value;
6420         gchar *utf8_name;
6421
6422         MONO_ARCH_SAVE_REGS;
6423
6424         if (name == NULL)
6425                 return NULL;
6426
6427         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6428         value = g_getenv (utf8_name);
6429
6430         g_free (utf8_name);
6431
6432         if (value == 0)
6433                 return NULL;
6434         
6435         return mono_string_new (mono_domain_get (), value);
6436 }
6437
6438 /*
6439  * There is no standard way to get at environ.
6440  */
6441 #ifndef _MSC_VER
6442 #ifndef __MINGW32_VERSION
6443 #ifdef __APPLE__
6444 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6445  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6446  * in fact exist on all implementations (so far) 
6447  */
6448 gchar ***_NSGetEnviron();
6449 #define environ (*_NSGetEnviron())
6450 #else
6451 extern
6452 char **environ;
6453 #endif
6454 #endif
6455 #endif
6456
6457 static MonoArray *
6458 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6459 {
6460 #ifdef PLATFORM_WIN32
6461         MonoArray *names;
6462         MonoDomain *domain;
6463         MonoString *str;
6464         WCHAR* env_strings;
6465         WCHAR* env_string;
6466         WCHAR* equal_str;
6467         int n = 0;
6468
6469         env_strings = GetEnvironmentStrings();
6470
6471         if (env_strings) {
6472                 env_string = env_strings;
6473                 while (*env_string != '\0') {
6474                 /* weird case that MS seems to skip */
6475                         if (*env_string != '=')
6476                                 n++;
6477                         while (*env_string != '\0')
6478                                 env_string++;
6479                         env_string++;
6480                 }
6481         }
6482
6483         domain = mono_domain_get ();
6484         names = mono_array_new (domain, mono_defaults.string_class, n);
6485
6486         if (env_strings) {
6487                 n = 0;
6488                 env_string = env_strings;
6489                 while (*env_string != '\0') {
6490                         /* weird case that MS seems to skip */
6491                         if (*env_string != '=') {
6492                                 equal_str = wcschr(env_string, '=');
6493                                 g_assert(equal_str);
6494                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6495                                 mono_array_setref (names, n, str);
6496                                 n++;
6497                         }
6498                         while (*env_string != '\0')
6499                                 env_string++;
6500                         env_string++;
6501                 }
6502
6503                 FreeEnvironmentStrings (env_strings);
6504         }
6505
6506         return names;
6507
6508 #else
6509         MonoArray *names;
6510         MonoDomain *domain;
6511         MonoString *str;
6512         gchar **e, **parts;
6513         int n;
6514
6515         MONO_ARCH_SAVE_REGS;
6516
6517         n = 0;
6518         for (e = environ; *e != 0; ++ e)
6519                 ++ n;
6520
6521         domain = mono_domain_get ();
6522         names = mono_array_new (domain, mono_defaults.string_class, n);
6523
6524         n = 0;
6525         for (e = environ; *e != 0; ++ e) {
6526                 parts = g_strsplit (*e, "=", 2);
6527                 if (*parts != 0) {
6528                         str = mono_string_new (domain, *parts);
6529                         mono_array_setref (names, n, str);
6530                 }
6531
6532                 g_strfreev (parts);
6533
6534                 ++ n;
6535         }
6536
6537         return names;
6538 #endif
6539 }
6540
6541 /*
6542  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6543  */
6544 #if !GLIB_CHECK_VERSION(2,4,0)
6545 #define g_setenv(a,b,c)   setenv(a,b,c)
6546 #define g_unsetenv(a) unsetenv(a)
6547 #endif
6548
6549 static void
6550 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6551 {
6552 #ifdef PLATFORM_WIN32
6553         gunichar2 *utf16_name, *utf16_value;
6554 #else
6555         gchar *utf8_name, *utf8_value;
6556 #endif
6557
6558         MONO_ARCH_SAVE_REGS;
6559         
6560 #ifdef PLATFORM_WIN32
6561         utf16_name = mono_string_to_utf16 (name);
6562         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6563                 SetEnvironmentVariable (utf16_name, NULL);
6564                 g_free (utf16_name);
6565                 return;
6566         }
6567
6568         utf16_value = mono_string_to_utf16 (value);
6569
6570         SetEnvironmentVariable (utf16_name, utf16_value);
6571
6572         g_free (utf16_name);
6573         g_free (utf16_value);
6574 #else
6575         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6576
6577         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6578                 g_unsetenv (utf8_name);
6579                 g_free (utf8_name);
6580                 return;
6581         }
6582
6583         utf8_value = mono_string_to_utf8 (value);
6584         g_setenv (utf8_name, utf8_value, TRUE);
6585
6586         g_free (utf8_name);
6587         g_free (utf8_value);
6588 #endif
6589 }
6590
6591 static void
6592 ves_icall_System_Environment_Exit (int result)
6593 {
6594         MONO_ARCH_SAVE_REGS;
6595
6596         mono_threads_set_shutting_down ();
6597
6598         mono_runtime_set_shutting_down ();
6599
6600         /* Suspend all managed threads since the runtime is going away */
6601         mono_thread_suspend_all_other_threads ();
6602
6603         mono_runtime_quit ();
6604
6605         /* we may need to do some cleanup here... */
6606         exit (result);
6607 }
6608
6609 static MonoString*
6610 ves_icall_System_Environment_GetGacPath (void)
6611 {
6612         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6613 }
6614
6615 static MonoString*
6616 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6617 {
6618 #if defined (PLATFORM_WIN32)
6619         #ifndef CSIDL_FLAG_CREATE
6620                 #define CSIDL_FLAG_CREATE       0x8000
6621         #endif
6622
6623         WCHAR path [MAX_PATH];
6624         /* Create directory if no existing */
6625         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6626                 int len = 0;
6627                 while (path [len])
6628                         ++ len;
6629                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6630         }
6631 #else
6632         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6633 #endif
6634         return mono_string_new (mono_domain_get (), "");
6635 }
6636
6637 static MonoArray *
6638 ves_icall_System_Environment_GetLogicalDrives (void)
6639 {
6640         gunichar2 buf [128], *ptr, *dname;
6641         gunichar2 *u16;
6642         guint initial_size = 127, size = 128;
6643         gint ndrives;
6644         MonoArray *result;
6645         MonoString *drivestr;
6646         MonoDomain *domain = mono_domain_get ();
6647         gint len;
6648
6649         MONO_ARCH_SAVE_REGS;
6650
6651         buf [0] = '\0';
6652         ptr = buf;
6653
6654         while (size > initial_size) {
6655                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6656                 if (size > initial_size) {
6657                         if (ptr != buf)
6658                                 g_free (ptr);
6659                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6660                         initial_size = size;
6661                         size++;
6662                 }
6663         }
6664
6665         /* Count strings */
6666         dname = ptr;
6667         ndrives = 0;
6668         do {
6669                 while (*dname++);
6670                 ndrives++;
6671         } while (*dname);
6672
6673         dname = ptr;
6674         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6675         ndrives = 0;
6676         do {
6677                 len = 0;
6678                 u16 = dname;
6679                 while (*u16) { u16++; len ++; }
6680                 drivestr = mono_string_new_utf16 (domain, dname, len);
6681                 mono_array_setref (result, ndrives++, drivestr);
6682                 while (*dname++);
6683         } while (*dname);
6684
6685         if (ptr != buf)
6686                 g_free (ptr);
6687
6688         return result;
6689 }
6690
6691 static MonoString *
6692 ves_icall_System_Environment_InternalGetHome (void)
6693 {
6694         MONO_ARCH_SAVE_REGS;
6695
6696         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6697 }
6698
6699 static const char *encodings [] = {
6700         (char *) 1,
6701                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6702                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6703                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6704         (char *) 2,
6705                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6706                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6707                 "x_unicode_2_0_utf_7",
6708         (char *) 3,
6709                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6710                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6711         (char *) 4,
6712                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6713                 "iso_10646_ucs2",
6714         (char *) 5,
6715                 "unicodefffe", "utf_16be",
6716         (char *) 6,
6717                 "iso_8859_1",
6718         (char *) 0
6719 };
6720
6721 /*
6722  * Returns the internal codepage, if the value of "int_code_page" is
6723  * 1 at entry, and we can not compute a suitable code page number,
6724  * returns the code page as a string
6725  */
6726 static MonoString*
6727 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6728 {
6729         const char *cset;
6730         const char *p;
6731         char *c;
6732         char *codepage = NULL;
6733         int code;
6734         int want_name = *int_code_page;
6735         int i;
6736         
6737         *int_code_page = -1;
6738         MONO_ARCH_SAVE_REGS;
6739
6740         g_get_charset (&cset);
6741         c = codepage = strdup (cset);
6742         for (c = codepage; *c; c++){
6743                 if (isascii (*c) && isalpha (*c))
6744                         *c = tolower (*c);
6745                 if (*c == '-')
6746                         *c = '_';
6747         }
6748         /* g_print ("charset: %s\n", cset); */
6749         
6750         /* handle some common aliases */
6751         p = encodings [0];
6752         code = 0;
6753         for (i = 0; p != 0; ){
6754                 if ((gssize) p < 7){
6755                         code = (gssize) p;
6756                         p = encodings [++i];
6757                         continue;
6758                 }
6759                 if (strcmp (p, codepage) == 0){
6760                         *int_code_page = code;
6761                         break;
6762                 }
6763                 p = encodings [++i];
6764         }
6765         
6766         if (strstr (codepage, "utf_8") != NULL)
6767                 *int_code_page |= 0x10000000;
6768         free (codepage);
6769         
6770         if (want_name && *int_code_page == -1)
6771                 return mono_string_new (mono_domain_get (), cset);
6772         else
6773                 return NULL;
6774 }
6775
6776 static MonoBoolean
6777 ves_icall_System_Environment_get_HasShutdownStarted (void)
6778 {
6779         if (mono_runtime_is_shutting_down ())
6780                 return TRUE;
6781
6782         if (mono_domain_is_unloading (mono_domain_get ()))
6783                 return TRUE;
6784
6785         return FALSE;
6786 }
6787
6788 static void
6789 ves_icall_System_Environment_BroadcastSettingChange (void)
6790 {
6791 #ifdef PLATFORM_WIN32
6792         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6793 #endif
6794 }
6795
6796 static void
6797 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6798                                          MonoReflectionMethod *method,
6799                                          MonoArray *out_args)
6800 {
6801         MONO_ARCH_SAVE_REGS;
6802
6803         mono_message_init (mono_object_domain (this), this, method, out_args);
6804 }
6805
6806 static MonoBoolean
6807 ves_icall_IsTransparentProxy (MonoObject *proxy)
6808 {
6809         MONO_ARCH_SAVE_REGS;
6810
6811         if (!proxy)
6812                 return 0;
6813
6814         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6815                 return 1;
6816
6817         return 0;
6818 }
6819
6820 static MonoReflectionMethod *
6821 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6822         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6823 {
6824         MonoClass *klass;
6825         MonoMethod *method;
6826         MonoMethod **vtable;
6827         MonoMethod *res = NULL;
6828
6829         MONO_CHECK_ARG_NULL (rtype);
6830         MONO_CHECK_ARG_NULL (rmethod);
6831
6832         method = rmethod->method;
6833         klass = mono_class_from_mono_type (rtype->type);
6834
6835         if (MONO_CLASS_IS_INTERFACE (klass))
6836                 return NULL;
6837
6838         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6839                 return NULL;
6840
6841         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6842                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6843                         return rmethod;
6844                 else
6845                         return NULL;
6846         }
6847
6848         mono_class_setup_vtable (klass);
6849         vtable = klass->vtable;
6850
6851         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6852                 int offs = mono_class_interface_offset (klass, method->klass);
6853                 if (offs >= 0)
6854                         res = vtable [offs + method->slot];
6855         } else {
6856                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6857                         return NULL;
6858
6859                 if (method->slot != -1)
6860                         res = vtable [method->slot];
6861         }
6862
6863         if (!res)
6864                 return NULL;
6865
6866         return mono_method_get_object (mono_domain_get (), res, NULL);
6867 }
6868
6869 static void
6870 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6871 {
6872         MonoClass *klass;
6873         MonoVTable* vtable;
6874
6875         MONO_ARCH_SAVE_REGS;
6876
6877         klass = mono_class_from_mono_type (type->type);
6878         vtable = mono_class_vtable (mono_domain_get (), klass);
6879
6880         if (enable) vtable->remote = 1;
6881         else vtable->remote = 0;
6882 }
6883
6884 static MonoObject *
6885 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6886 {
6887         MonoClass *klass;
6888         MonoDomain *domain;
6889         
6890         MONO_ARCH_SAVE_REGS;
6891
6892         domain = mono_object_domain (type);
6893         klass = mono_class_from_mono_type (type->type);
6894
6895         if (klass->rank >= 1) {
6896                 g_assert (klass->rank == 1);
6897                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6898         } else {
6899                 /* Bypass remoting object creation check */
6900                 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6901         }
6902 }
6903
6904 static MonoString *
6905 ves_icall_System_IO_get_temp_path (void)
6906 {
6907         MONO_ARCH_SAVE_REGS;
6908
6909         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6910 }
6911
6912 static MonoBoolean
6913 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6914                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6915                                                 gint32 *error)
6916 {
6917         gboolean result;
6918         ULARGE_INTEGER wapi_free_bytes_avail;
6919         ULARGE_INTEGER wapi_total_number_of_bytes;
6920         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6921
6922         MONO_ARCH_SAVE_REGS;
6923
6924         *error = ERROR_SUCCESS;
6925         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6926                                      &wapi_total_number_of_free_bytes);
6927
6928         if (result) {
6929                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6930                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6931                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6932         } else {
6933                 *free_bytes_avail = 0;
6934                 *total_number_of_bytes = 0;
6935                 *total_number_of_free_bytes = 0;
6936                 *error = GetLastError ();
6937         }
6938
6939         return result;
6940 }
6941
6942 static guint32
6943 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6944 {
6945         MONO_ARCH_SAVE_REGS;
6946
6947         return GetDriveType (mono_string_chars (root_path_name));
6948 }
6949
6950 static gpointer
6951 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6952 {
6953         MONO_ARCH_SAVE_REGS;
6954
6955         return mono_compile_method (method);
6956 }
6957
6958 static MonoString *
6959 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6960 {
6961         MonoString *mcpath;
6962         gchar *path;
6963
6964         MONO_ARCH_SAVE_REGS;
6965
6966         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6967
6968 #if defined (PLATFORM_WIN32)
6969         /* Avoid mixing '/' and '\\' */
6970         {
6971                 gint i;
6972                 for (i = strlen (path) - 1; i >= 0; i--)
6973                         if (path [i] == '/')
6974                                 path [i] = '\\';
6975         }
6976 #endif
6977         mcpath = mono_string_new (mono_domain_get (), path);
6978         g_free (path);
6979
6980         return mcpath;
6981 }
6982
6983 static MonoString *
6984 get_bundled_machine_config (void)
6985 {
6986         const gchar *machine_config;
6987
6988         MONO_ARCH_SAVE_REGS;
6989
6990         machine_config = mono_get_machine_config ();
6991
6992         if (!machine_config)
6993                 return NULL;
6994
6995         return mono_string_new (mono_domain_get (), machine_config);
6996 }
6997
6998 static MonoString *
6999 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7000 {
7001         MonoString *ipath;
7002         gchar *path;
7003
7004         MONO_ARCH_SAVE_REGS;
7005
7006         path = g_path_get_dirname (mono_get_config_dir ());
7007
7008 #if defined (PLATFORM_WIN32)
7009         /* Avoid mixing '/' and '\\' */
7010         {
7011                 gint i;
7012                 for (i = strlen (path) - 1; i >= 0; i--)
7013                         if (path [i] == '/')
7014                                 path [i] = '\\';
7015         }
7016 #endif
7017         ipath = mono_string_new (mono_domain_get (), path);
7018         g_free (path);
7019
7020         return ipath;
7021 }
7022
7023 static MonoBoolean
7024 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7025 {
7026         return mono_debug_using_mono_debugger ();
7027 }
7028
7029 static void
7030 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7031 {
7032 #if defined (PLATFORM_WIN32)
7033         OutputDebugString (mono_string_chars (message));
7034 #else
7035         g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7036 #endif
7037 }
7038
7039 /* Only used for value types */
7040 static MonoObject *
7041 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7042 {
7043         MonoClass *klass;
7044         MonoDomain *domain;
7045         
7046         MONO_ARCH_SAVE_REGS;
7047
7048         domain = mono_object_domain (type);
7049         klass = mono_class_from_mono_type (type->type);
7050
7051         if (mono_class_is_nullable (klass))
7052                 /* No arguments -> null */
7053                 return NULL;
7054
7055         return mono_object_new (domain, klass);
7056 }
7057
7058 static MonoReflectionMethod *
7059 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7060 {
7061         MonoClass *klass, *parent;
7062         MonoMethod *method = m->method;
7063         MonoMethod *result = NULL;
7064
7065         MONO_ARCH_SAVE_REGS;
7066
7067         if (method->klass == NULL)
7068                 return m;
7069
7070         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7071             MONO_CLASS_IS_INTERFACE (method->klass) ||
7072             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7073                 return m;
7074
7075         klass = method->klass;
7076         if (klass->generic_class)
7077                 klass = klass->generic_class->container_class;
7078
7079         /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7080         for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7081                 mono_class_setup_vtable (parent);
7082                 if (parent->vtable_size <= method->slot)
7083                         break;
7084                 klass = parent;
7085         }               
7086
7087         if (klass == method->klass)
7088                 return m;
7089
7090         result = klass->vtable [method->slot];
7091         if (result == NULL) {
7092                 /* It is an abstract method */
7093                 gpointer iter = NULL;
7094                 while ((result = mono_class_get_methods (klass, &iter)))
7095                         if (result->slot == method->slot)
7096                                 break;
7097         }
7098
7099         if (result == NULL)
7100                 return m;
7101
7102         return mono_method_get_object (mono_domain_get (), result, NULL);
7103 }
7104
7105 static MonoString*
7106 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7107 {
7108         MonoMethod *method = m->method;
7109
7110         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7111         return m->name;
7112 }
7113
7114 static void
7115 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7116 {
7117         MONO_ARCH_SAVE_REGS;
7118
7119         iter->sig = *(MonoMethodSignature**)argsp;
7120         
7121         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7122         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7123
7124         iter->next_arg = 0;
7125         /* FIXME: it's not documented what start is exactly... */
7126         if (start) {
7127                 iter->args = start;
7128         } else {
7129                 guint32 i, arg_size;
7130                 gint32 align;
7131                 iter->args = argsp + sizeof (gpointer);
7132 #ifndef MONO_ARCH_REGPARMS
7133                 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7134                         arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7135                         iter->args = (char*)iter->args + arg_size;
7136                 }
7137 #endif
7138         }
7139         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7140
7141         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7142 }
7143
7144 static MonoTypedRef
7145 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7146 {
7147         guint32 i, arg_size;
7148         gint32 align;
7149         MonoTypedRef res;
7150         MONO_ARCH_SAVE_REGS;
7151
7152         i = iter->sig->sentinelpos + iter->next_arg;
7153
7154         g_assert (i < iter->sig->param_count);
7155
7156         res.type = iter->sig->params [i];
7157         res.klass = mono_class_from_mono_type (res.type);
7158         res.value = iter->args;
7159         arg_size = mono_type_stack_size (res.type, &align);
7160 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7161         if (arg_size <= sizeof (gpointer)) {
7162                 int dummy;
7163                 int padding = arg_size - mono_type_size (res.type, &dummy);
7164                 res.value = (guint8*)res.value + padding;
7165         }
7166 #endif
7167         iter->args = (char*)iter->args + arg_size;
7168         iter->next_arg++;
7169
7170         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7171
7172         return res;
7173 }
7174
7175 static MonoTypedRef
7176 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7177 {
7178         guint32 i, arg_size;
7179         gint32 align;
7180         MonoTypedRef res;
7181         MONO_ARCH_SAVE_REGS;
7182
7183         i = iter->sig->sentinelpos + iter->next_arg;
7184
7185         g_assert (i < iter->sig->param_count);
7186
7187         while (i < iter->sig->param_count) {
7188                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7189                         continue;
7190                 res.type = iter->sig->params [i];
7191                 res.klass = mono_class_from_mono_type (res.type);
7192                 /* FIXME: endianess issue... */
7193                 res.value = iter->args;
7194                 arg_size = mono_type_stack_size (res.type, &align);
7195                 iter->args = (char*)iter->args + arg_size;
7196                 iter->next_arg++;
7197                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7198                 return res;
7199         }
7200         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7201
7202         res.type = NULL;
7203         res.value = NULL;
7204         res.klass = NULL;
7205         return res;
7206 }
7207
7208 static MonoType*
7209 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7210 {
7211         gint i;
7212         MONO_ARCH_SAVE_REGS;
7213         
7214         i = iter->sig->sentinelpos + iter->next_arg;
7215
7216         g_assert (i < iter->sig->param_count);
7217
7218         return iter->sig->params [i];
7219 }
7220
7221 static MonoObject*
7222 mono_TypedReference_ToObject (MonoTypedRef tref)
7223 {
7224         MONO_ARCH_SAVE_REGS;
7225
7226         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7227                 MonoObject** objp = tref.value;
7228                 return *objp;
7229         }
7230
7231         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7232 }
7233
7234 static MonoObject*
7235 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7236 {
7237         MONO_ARCH_SAVE_REGS;
7238
7239         if (MONO_TYPE_IS_REFERENCE (type)) {
7240                 MonoObject** objp = value;
7241                 return *objp;
7242         }
7243
7244         return mono_value_box (mono_domain_get (), klass, value);
7245 }
7246
7247 static void
7248 prelink_method (MonoMethod *method)
7249 {
7250         const char *exc_class, *exc_arg;
7251         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7252                 return;
7253         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7254         if (exc_class) {
7255                 mono_raise_exception( 
7256                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7257         }
7258         /* create the wrapper, too? */
7259 }
7260
7261 static void
7262 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7263 {
7264         MONO_ARCH_SAVE_REGS;
7265         prelink_method (method->method);
7266 }
7267
7268 static void
7269 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7270 {
7271         MonoClass *klass = mono_class_from_mono_type (type->type);
7272         MonoMethod* m;
7273         gpointer iter = NULL;
7274         MONO_ARCH_SAVE_REGS;
7275
7276         while ((m = mono_class_get_methods (klass, &iter)))
7277                 prelink_method (m);
7278 }
7279
7280 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7281 static void
7282 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7283                                             gint32 const **exponents,
7284                                             gunichar2 const **digitLowerTable,
7285                                             gunichar2 const **digitUpperTable,
7286                                             gint64 const **tenPowersList,
7287                                             gint32 const **decHexDigits)
7288 {
7289         *mantissas = Formatter_MantissaBitsTable;
7290         *exponents = Formatter_TensExponentTable;
7291         *digitLowerTable = Formatter_DigitLowerTable;
7292         *digitUpperTable = Formatter_DigitUpperTable;
7293         *tenPowersList = Formatter_TenPowersList;
7294         *decHexDigits = Formatter_DecHexDigits;
7295 }
7296
7297 /* These parameters are "readonly" in corlib/System/Char.cs */
7298 static void
7299 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7300                                             guint8 const **numeric_data,
7301                                             gdouble const **numeric_data_values,
7302                                             guint16 const **to_lower_data_low,
7303                                             guint16 const **to_lower_data_high,
7304                                             guint16 const **to_upper_data_low,
7305                                             guint16 const **to_upper_data_high)
7306 {
7307         *category_data = CategoryData;
7308         *numeric_data = NumericData;
7309         *numeric_data_values = NumericDataValues;
7310         *to_lower_data_low = ToLowerDataLow;
7311         *to_lower_data_high = ToLowerDataHigh;
7312         *to_upper_data_low = ToUpperDataLow;
7313         *to_upper_data_high = ToUpperDataHigh;
7314 }
7315
7316 static gint32
7317 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7318 {
7319         return method->method->token;
7320 }
7321
7322 /*
7323  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7324  * and avoid useless allocations.
7325  */
7326 static MonoArray*
7327 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7328 {
7329         MonoArray *res;
7330         int i, count = 0;
7331         for (i = 0; i < type->num_mods; ++i) {
7332                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7333                         count++;
7334         }
7335         if (!count)
7336                 return NULL;
7337         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7338         count = 0;
7339         for (i = 0; i < type->num_mods; ++i) {
7340                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7341                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7342                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7343                         count++;
7344                 }
7345         }
7346         return res;
7347 }
7348
7349 static MonoArray*
7350 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7351 {
7352         MonoType *type = param->ClassImpl->type;
7353         MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7354         MonoImage *image = method->method->klass->image;
7355         int pos = param->PositionImpl;
7356         MonoMethodSignature *sig = mono_method_signature (method->method);
7357         if (pos == -1)
7358                 type = sig->ret;
7359         else
7360                 type = sig->params [pos];
7361
7362         return type_array_from_modifiers (image, type, optional);
7363 }
7364
7365 static MonoType*
7366 get_property_type (MonoProperty *prop)
7367 {
7368         MonoMethodSignature *sig;
7369         if (prop->get) {
7370                 sig = mono_method_signature (prop->get);
7371                 return sig->ret;
7372         } else if (prop->set) {
7373                 sig = mono_method_signature (prop->set);
7374                 return sig->params [sig->param_count - 1];
7375         }
7376         return NULL;
7377 }
7378
7379 static MonoArray*
7380 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7381 {
7382         MonoType *type = get_property_type (property->property);
7383         MonoImage *image = property->klass->image;
7384
7385         if (!type)
7386                 return NULL;
7387         return type_array_from_modifiers (image, type, optional);
7388 }
7389
7390 static MonoBoolean
7391 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7392 {
7393         MonoCustomAttrInfo *cinfo;
7394         gboolean found;
7395
7396         cinfo = mono_reflection_get_custom_attrs_info (obj);
7397         if (!cinfo)
7398                 return FALSE;
7399         found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7400         if (!cinfo->cached)
7401                 mono_custom_attrs_free (cinfo);
7402         return found;
7403 }
7404
7405 static MonoArray*
7406 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7407 {
7408         MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7409
7410         if (mono_loader_get_last_error ()) {
7411                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7412                 g_assert_not_reached ();
7413         } else {
7414                 return res;
7415         }
7416 }
7417
7418 static MonoBoolean
7419 GCHandle_CheckCurrentDomain (guint32 gchandle)
7420 {
7421         return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7422 }
7423
7424 static MonoString*
7425 ves_icall_Mono_Runtime_GetDisplayName (void)
7426 {
7427         static const char display_name_str [] = "Mono " VERSION;
7428         MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7429         return display_name;
7430 }
7431
7432 static MonoString*
7433 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7434 {
7435         MonoString *message;
7436         guint32 ret;
7437         gunichar2 buf[256];
7438         
7439         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7440                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7441                              buf, 255, NULL);
7442         if (ret == 0) {
7443                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7444         } else {
7445                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7446         }
7447         
7448         return message;
7449 }
7450
7451 const static guchar
7452 dbase64 [] = {
7453         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7454         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7455         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7456         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7457         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7458         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7459         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7460         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7461 };
7462
7463 static MonoArray *
7464 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7465 {
7466         gint ignored;
7467         gint i;
7468         gunichar2 c;
7469         gunichar2 last, prev_last, prev2_last;
7470         gint olength;
7471         MonoArray *result;
7472         guchar *res_ptr;
7473         gint a [4], b [4];
7474         MonoException *exc;
7475
7476         ignored = 0;
7477         last = prev_last = 0, prev2_last = 0;
7478         for (i = 0; i < ilength; i++) {
7479                 c = start [i];
7480                 if (c >= sizeof (dbase64)) {
7481                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7482                                 "System", "FormatException",
7483                                 "Invalid character found.");
7484                         mono_raise_exception (exc);
7485                 } else if (isspace (c)) {
7486                         ignored++;
7487                 } else {
7488                         prev2_last = prev_last;
7489                         prev_last = last;
7490                         last = c;
7491                 }
7492         }
7493
7494         olength = ilength - ignored;
7495
7496         if (allowWhitespaceOnly && olength == 0) {
7497                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7498         }
7499
7500         if ((olength & 3) != 0 || olength <= 0) {
7501                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7502                                         "FormatException", "Invalid length.");
7503                 mono_raise_exception (exc);
7504         }
7505
7506         if (prev2_last == '=') {
7507                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7508                 mono_raise_exception (exc);
7509         }
7510
7511         olength = (olength * 3) / 4;
7512         if (last == '=')
7513                 olength--;
7514
7515         if (prev_last == '=')
7516                 olength--;
7517
7518         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7519         res_ptr = mono_array_addr (result, guchar, 0);
7520         for (i = 0; i < ilength; ) {
7521                 int k;
7522
7523                 for (k = 0; k < 4 && i < ilength;) {
7524                         c = start [i++];
7525                         if (isspace (c))
7526                                 continue;
7527
7528                         a [k] = (guchar) c;
7529                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7530                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7531                                         "System", "FormatException",
7532                                         "Invalid character found.");
7533                                 mono_raise_exception (exc);
7534                         }
7535                         k++;
7536                 }
7537
7538                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7539                 if (a [2] != '=')
7540                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7541                 if (a [3] != '=')
7542                         *res_ptr++ = (b [2] << 6) | b [3];
7543
7544                 while (i < ilength && isspace (start [i]))
7545                         i++;
7546         }
7547
7548         return result;
7549 }
7550
7551 static MonoArray *
7552 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7553 {
7554         MONO_ARCH_SAVE_REGS;
7555
7556         return base64_to_byte_array (mono_string_chars (str), 
7557                 mono_string_length (str), allowWhitespaceOnly);
7558 }
7559
7560 static MonoArray *
7561 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7562 {
7563         MONO_ARCH_SAVE_REGS;
7564
7565         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7566                 length, FALSE);
7567 }
7568
7569 #define ICALL_TYPE(id,name,first)
7570 #define ICALL(id,name,func) Icall_ ## id,
7571
7572 enum {
7573 #include "metadata/icall-def.h"
7574         Icall_last
7575 };
7576
7577 #undef ICALL_TYPE
7578 #undef ICALL
7579 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7580 #define ICALL(id,name,func)
7581 enum {
7582 #include "metadata/icall-def.h"
7583         Icall_type_num
7584 };
7585
7586 #undef ICALL_TYPE
7587 #undef ICALL
7588 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7589 #define ICALL(id,name,func)
7590 typedef struct {
7591         guint16 first_icall;
7592 } IcallTypeDesc;
7593
7594 static const IcallTypeDesc
7595 icall_type_descs [] = {
7596 #include "metadata/icall-def.h"
7597         {Icall_last}
7598 };
7599
7600 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7601
7602 #undef ICALL_TYPE
7603 #define ICALL_TYPE(id,name,first)
7604 #undef ICALL
7605
7606 #ifdef HAVE_ARRAY_ELEM_INIT
7607 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7608 #define MSGSTRFIELD1(line) str##line
7609
7610 static const struct msgstrtn_t {
7611 #define ICALL(id,name,func)
7612 #undef ICALL_TYPE
7613 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7614 #include "metadata/icall-def.h"
7615 #undef ICALL_TYPE
7616 } icall_type_names_str = {
7617 #define ICALL_TYPE(id,name,first) (name),
7618 #include "metadata/icall-def.h"
7619 #undef ICALL_TYPE
7620 };
7621 static const guint16 icall_type_names_idx [] = {
7622 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7623 #include "metadata/icall-def.h"
7624 #undef ICALL_TYPE
7625 };
7626 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7627
7628 static const struct msgstr_t {
7629 #undef ICALL
7630 #define ICALL_TYPE(id,name,first)
7631 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7632 #include "metadata/icall-def.h"
7633 #undef ICALL
7634 } icall_names_str = {
7635 #define ICALL(id,name,func) (name),
7636 #include "metadata/icall-def.h"
7637 #undef ICALL
7638 };
7639 static const guint16 icall_names_idx [] = {
7640 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7641 #include "metadata/icall-def.h"
7642 #undef ICALL
7643 };
7644 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7645
7646 #else
7647
7648 #undef ICALL_TYPE
7649 #undef ICALL
7650 #define ICALL_TYPE(id,name,first) name,
7651 #define ICALL(id,name,func)
7652 static const char* const
7653 icall_type_names [] = {
7654 #include "metadata/icall-def.h"
7655         NULL
7656 };
7657
7658 #define icall_type_name_get(id) (icall_type_names [(id)])
7659
7660 #undef ICALL_TYPE
7661 #undef ICALL
7662 #define ICALL_TYPE(id,name,first)
7663 #define ICALL(id,name,func) name,
7664 static const char* const
7665 icall_names [] = {
7666 #include "metadata/icall-def.h"
7667         NULL
7668 };
7669 #define icall_name_get(id) icall_names [(id)]
7670
7671 #endif /* !HAVE_ARRAY_ELEM_INIT */
7672
7673 #undef ICALL_TYPE
7674 #undef ICALL
7675 #define ICALL_TYPE(id,name,first)
7676 #define ICALL(id,name,func) func,
7677 static const gconstpointer
7678 icall_functions [] = {
7679 #include "metadata/icall-def.h"
7680         NULL
7681 };
7682
7683 static GHashTable *icall_hash = NULL;
7684 static GHashTable *jit_icall_hash_name = NULL;
7685 static GHashTable *jit_icall_hash_addr = NULL;
7686
7687 void
7688 mono_icall_init (void)
7689 {
7690         int i = 0;
7691
7692         /* check that tables are sorted: disable in release */
7693         if (TRUE) {
7694                 int j;
7695                 const char *prev_class = NULL;
7696                 const char *prev_method;
7697                 
7698                 for (i = 0; i < Icall_type_num; ++i) {
7699                         const IcallTypeDesc *desc;
7700                         int num_icalls;
7701                         prev_method = NULL;
7702                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7703                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7704                         prev_class = icall_type_name_get (i);
7705                         desc = &icall_type_descs [i];
7706                         num_icalls = icall_desc_num_icalls (desc);
7707                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7708                         for (j = 0; j < num_icalls; ++j) {
7709                                 const char *methodn = icall_name_get (desc->first_icall + j);
7710                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7711                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7712                                 prev_method = methodn;
7713                         }
7714                 }
7715         }
7716
7717         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7718 }
7719
7720 void
7721 mono_icall_cleanup (void)
7722 {
7723         g_hash_table_destroy (icall_hash);
7724         g_hash_table_destroy (jit_icall_hash_name);
7725         g_hash_table_destroy (jit_icall_hash_addr);
7726 }
7727
7728 void
7729 mono_add_internal_call (const char *name, gconstpointer method)
7730 {
7731         mono_loader_lock ();
7732
7733         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7734
7735         mono_loader_unlock ();
7736 }
7737
7738 #ifdef HAVE_ARRAY_ELEM_INIT
7739 static int
7740 compare_method_imap (const void *key, const void *elem)
7741 {
7742         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7743         return strcmp (key, method_name);
7744 }
7745
7746 static gpointer
7747 find_method_icall (const IcallTypeDesc *imap, const char *name)
7748 {
7749         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7750         if (!nameslot)
7751                 return NULL;
7752         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7753 }
7754
7755 static int
7756 compare_class_imap (const void *key, const void *elem)
7757 {
7758         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7759         return strcmp (key, class_name);
7760 }
7761
7762 static const IcallTypeDesc*
7763 find_class_icalls (const char *name)
7764 {
7765         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7766         if (!nameslot)
7767                 return NULL;
7768         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7769 }
7770
7771 #else
7772 static int
7773 compare_method_imap (const void *key, const void *elem)
7774 {
7775         const char** method_name = (const char**)elem;
7776         return strcmp (key, *method_name);
7777 }
7778
7779 static gpointer
7780 find_method_icall (const IcallTypeDesc *imap, const char *name)
7781 {
7782         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7783         if (!nameslot)
7784                 return NULL;
7785         return (gpointer)icall_functions [(nameslot - icall_names)];
7786 }
7787
7788 static int
7789 compare_class_imap (const void *key, const void *elem)
7790 {
7791         const char** class_name = (const char**)elem;
7792         return strcmp (key, *class_name);
7793 }
7794
7795 static const IcallTypeDesc*
7796 find_class_icalls (const char *name)
7797 {
7798         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7799         if (!nameslot)
7800                 return NULL;
7801         return &icall_type_descs [nameslot - icall_type_names];
7802 }
7803
7804 #endif
7805
7806 /* 
7807  * we should probably export this as an helper (handle nested types).
7808  * Returns the number of chars written in buf.
7809  */
7810 static int
7811 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7812 {
7813         int nspacelen, cnamelen;
7814         nspacelen = strlen (klass->name_space);
7815         cnamelen = strlen (klass->name);
7816         if (nspacelen + cnamelen + 2 > bufsize)
7817                 return 0;
7818         if (nspacelen) {
7819                 memcpy (buf, klass->name_space, nspacelen);
7820                 buf [nspacelen ++] = '.';
7821         }
7822         memcpy (buf + nspacelen, klass->name, cnamelen);
7823         buf [nspacelen + cnamelen] = 0;
7824         return nspacelen + cnamelen;
7825 }
7826
7827 gpointer
7828 mono_lookup_internal_call (MonoMethod *method)
7829 {
7830         char *sigstart;
7831         char *tmpsig;
7832         char mname [2048];
7833         int typelen = 0, mlen, siglen;
7834         gpointer res;
7835         const IcallTypeDesc *imap;
7836
7837         g_assert (method != NULL);
7838
7839         if (method->is_inflated)
7840                 method = ((MonoMethodInflated *) method)->declaring;
7841
7842         if (method->klass->nested_in) {
7843                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7844                 if (!pos)
7845                         return NULL;
7846
7847                 mname [pos++] = '/';
7848                 mname [pos] = 0;
7849
7850                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7851                 if (!typelen)
7852                         return NULL;
7853
7854                 typelen += pos;
7855         } else {
7856                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7857                 if (!typelen)
7858                         return NULL;
7859         }
7860
7861         imap = find_class_icalls (mname);
7862
7863         mname [typelen] = ':';
7864         mname [typelen + 1] = ':';
7865
7866         mlen = strlen (method->name);
7867         memcpy (mname + typelen + 2, method->name, mlen);
7868         sigstart = mname + typelen + 2 + mlen;
7869         *sigstart = 0;
7870
7871         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7872         siglen = strlen (tmpsig);
7873         if (typelen + mlen + siglen + 6 > sizeof (mname))
7874                 return NULL;
7875         sigstart [0] = '(';
7876         memcpy (sigstart + 1, tmpsig, siglen);
7877         sigstart [siglen + 1] = ')';
7878         sigstart [siglen + 2] = 0;
7879         g_free (tmpsig);
7880         
7881         mono_loader_lock ();
7882
7883         res = g_hash_table_lookup (icall_hash, mname);
7884         if (res) {
7885                 mono_loader_unlock ();
7886                 return res;
7887         }
7888         /* try without signature */
7889         *sigstart = 0;
7890         res = g_hash_table_lookup (icall_hash, mname);
7891         if (res) {
7892                 mono_loader_unlock ();
7893                 return res;
7894         }
7895
7896         /* it wasn't found in the static call tables */
7897         if (!imap) {
7898                 mono_loader_unlock ();
7899                 return NULL;
7900         }
7901         res = find_method_icall (imap, sigstart - mlen);
7902         if (res) {
7903                 mono_loader_unlock ();
7904                 return res;
7905         }
7906         /* try _with_ signature */
7907         *sigstart = '(';
7908         res = find_method_icall (imap, sigstart - mlen);
7909         if (res) {
7910                 mono_loader_unlock ();
7911                 return res;
7912         }
7913
7914         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7915         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7916         g_print ("The out of sync library is: %s\n", method->klass->image->name);
7917         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7918         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");
7919         g_print ("If you see other errors or faults after this message they are probably related\n");
7920         g_print ("and you need to fix your mono install first.\n");
7921
7922         mono_loader_unlock ();
7923
7924         return NULL;
7925 }
7926
7927 static MonoType*
7928 type_from_typename (char *typename)
7929 {
7930         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
7931
7932         if (!strcmp (typename, "int"))
7933                 klass = mono_defaults.int_class;
7934         else if (!strcmp (typename, "ptr"))
7935                 klass = mono_defaults.int_class;
7936         else if (!strcmp (typename, "void"))
7937                 klass = mono_defaults.void_class;
7938         else if (!strcmp (typename, "int32"))
7939                 klass = mono_defaults.int32_class;
7940         else if (!strcmp (typename, "uint32"))
7941                 klass = mono_defaults.uint32_class;
7942         else if (!strcmp (typename, "int8"))
7943                 klass = mono_defaults.sbyte_class;
7944         else if (!strcmp (typename, "uint8"))
7945                 klass = mono_defaults.byte_class;
7946         else if (!strcmp (typename, "int16"))
7947                 klass = mono_defaults.int16_class;
7948         else if (!strcmp (typename, "uint16"))
7949                 klass = mono_defaults.uint16_class;
7950         else if (!strcmp (typename, "long"))
7951                 klass = mono_defaults.int64_class;
7952         else if (!strcmp (typename, "ulong"))
7953                 klass = mono_defaults.uint64_class;
7954         else if (!strcmp (typename, "float"))
7955                 klass = mono_defaults.single_class;
7956         else if (!strcmp (typename, "double"))
7957                 klass = mono_defaults.double_class;
7958         else if (!strcmp (typename, "object"))
7959                 klass = mono_defaults.object_class;
7960         else if (!strcmp (typename, "obj"))
7961                 klass = mono_defaults.object_class;
7962         else if (!strcmp (typename, "string"))
7963                 klass = mono_defaults.string_class;
7964         else if (!strcmp (typename, "bool"))
7965                 klass = mono_defaults.boolean_class;
7966         else if (!strcmp (typename, "boolean"))
7967                 klass = mono_defaults.boolean_class;
7968         else {
7969                 g_error ("%s", typename);
7970                 g_assert_not_reached ();
7971         }
7972         return &klass->byval_arg;
7973 }
7974
7975 MonoMethodSignature*
7976 mono_create_icall_signature (const char *sigstr)
7977 {
7978         gchar **parts;
7979         int i, len;
7980         gchar **tmp;
7981         MonoMethodSignature *res;
7982
7983         mono_loader_lock ();
7984         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7985         if (res) {
7986                 mono_loader_unlock ();
7987                 return res;
7988         }
7989
7990         parts = g_strsplit (sigstr, " ", 256);
7991
7992         tmp = parts;
7993         len = 0;
7994         while (*tmp) {
7995                 len ++;
7996                 tmp ++;
7997         }
7998
7999         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8000         res->pinvoke = 1;
8001
8002 #ifdef PLATFORM_WIN32
8003         /* 
8004          * Under windows, the default pinvoke calling convention is STDCALL but
8005          * we need CDECL.
8006          */
8007         res->call_convention = MONO_CALL_C;
8008 #endif
8009
8010         res->ret = type_from_typename (parts [0]);
8011         for (i = 1; i < len; ++i) {
8012                 res->params [i - 1] = type_from_typename (parts [i]);
8013         }
8014
8015         g_strfreev (parts);
8016
8017         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8018
8019         mono_loader_unlock ();
8020
8021         return res;
8022 }
8023
8024 MonoJitICallInfo *
8025 mono_find_jit_icall_by_name (const char *name)
8026 {
8027         MonoJitICallInfo *info;
8028         g_assert (jit_icall_hash_name);
8029
8030         mono_loader_lock ();
8031         info = g_hash_table_lookup (jit_icall_hash_name, name);
8032         mono_loader_unlock ();
8033         return info;
8034 }
8035
8036 MonoJitICallInfo *
8037 mono_find_jit_icall_by_addr (gconstpointer addr)
8038 {
8039         MonoJitICallInfo *info;
8040         g_assert (jit_icall_hash_addr);
8041
8042         mono_loader_lock ();
8043         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8044         mono_loader_unlock ();
8045
8046         return info;
8047 }
8048
8049 /*
8050  * mono_get_jit_icall_info:
8051  *
8052  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8053  * caller should access it while holding the loader lock.
8054  */
8055 GHashTable*
8056 mono_get_jit_icall_info (void)
8057 {
8058         return jit_icall_hash_name;
8059 }
8060
8061 void
8062 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8063 {
8064         mono_loader_lock ();
8065         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8066         mono_loader_unlock ();
8067 }
8068
8069 MonoJitICallInfo *
8070 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8071 {
8072         MonoJitICallInfo *info;
8073         
8074         g_assert (func);
8075         g_assert (name);
8076
8077         mono_loader_lock ();
8078
8079         if (!jit_icall_hash_name) {
8080                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8081                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8082         }
8083
8084         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8085                 g_warning ("jit icall already defined \"%s\"\n", name);
8086                 g_assert_not_reached ();
8087         }
8088
8089         info = g_new0 (MonoJitICallInfo, 1);
8090         
8091         info->name = name;
8092         info->func = func;
8093         info->sig = sig;
8094
8095         if (is_save) {
8096                 info->wrapper = func;
8097         } else {
8098                 info->wrapper = NULL;
8099         }
8100
8101         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8102         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8103
8104         mono_loader_unlock ();
8105         return info;
8106 }