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