ppc changes
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <stdarg.h>
13 #include <string.h>
14 #include <sys/time.h>
15 #include <unistd.h>
16
17 #include <mono/metadata/object.h>
18 #include <mono/metadata/threads.h>
19 #include <mono/metadata/reflection.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/tabledefs.h>
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/file-io.h>
24 #include <mono/metadata/mono-endian.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/unicode.h>
27 #include "decimal.h"
28
29 static MonoObject *
30 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
31 {
32         MonoClass *ac, *ic;
33         MonoArray *ao, *io;
34         gint32 i, pos, *ind, esize;
35         gpointer *ea;
36
37         io = (MonoArray *)idxs;
38         ic = (MonoClass *)io->obj.klass;
39         
40         ao = (MonoArray *)this;
41         ac = (MonoClass *)ao->obj.klass;
42
43         g_assert (ic->rank == 1);
44         g_assert (io->bounds [0].length == ac->rank);
45
46         ind = (guint32 *)io->vector;
47
48         pos = ind [0] - ao->bounds [0].lower_bound;
49         for (i = 1; i < ac->rank; i++)
50                 pos = pos*ao->bounds [i].length + ind [i] - 
51                         ao->bounds [i].lower_bound;
52
53         esize = mono_array_element_size (ac);
54         ea = (gpointer*)((char*)ao->vector + (pos * esize));
55
56         if (ac->element_class->valuetype)
57                 return mono_value_box (ac->element_class, ea);
58         else {
59                 return *ea;
60         }
61 }
62
63 static void 
64 ves_icall_System_Array_SetValue (MonoObject *this, MonoObject *value,
65                                  MonoObject *idxs)
66 {
67         MonoArray *ao, *io, *vo;
68         MonoClass *ac, *ic, *vc;
69         gint32 i, pos, *ind, esize;
70         gpointer *ea;
71
72         vo = (MonoArray *)value;
73         vc = (MonoClass *)vo->obj.klass;
74
75         io = (MonoArray *)idxs;
76         ic = (MonoClass *)io->obj.klass;
77         
78         ao = (MonoArray *)this;
79         ac = (MonoClass *)ao->obj.klass;
80
81         g_assert (ic->rank == 1);
82         g_assert (io->bounds [0].length == ac->rank);
83         if (!mono_object_isinst (value, ac->element_class)) {
84                 g_error ("Array not compatible: %s <= %s", ac->element_class->name, vo->obj.klass->name);
85         }
86
87         ind = (guint32 *)io->vector;
88
89         pos = ind [0] - ao->bounds [0].lower_bound;
90         for (i = 1; i < ac->rank; i++)
91                 pos = pos*ao->bounds [i].length + ind [i] - 
92                         ao->bounds [i].lower_bound;
93
94         esize = mono_array_element_size (ac);
95         ea = (gpointer*)((char*)ao->vector + (pos * esize));
96
97         if (ac->element_class->valuetype) {
98                 g_assert (vc->valuetype);
99
100                 memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
101         } else
102                 *ea = (gpointer)vo;
103
104 }
105
106 static void
107 ves_icall_System_Array_CreateInstance ()
108 {
109         g_warning ("not implemented");
110         g_assert_not_reached ();
111 }
112
113
114 static gint32 
115 ves_icall_System_Array_GetRank (MonoObject *this)
116 {
117         return this->klass->rank;
118 }
119
120 static gint32
121 ves_icall_System_Array_GetLength (MonoObject *this, gint32 dimension)
122 {
123         return ((MonoArray *)this)->bounds [dimension].length;
124 }
125
126 static gint32
127 ves_icall_System_Array_GetLowerBound (MonoObject *this, gint32 dimension)
128 {
129         return ((MonoArray *)this)->bounds [dimension].lower_bound;
130 }
131
132 static void
133 ves_icall_InitializeArray (MonoArray *array, MonoClassField *field_handle)
134 {
135         MonoClass *klass = array->obj.klass;
136         guint32 size = mono_array_element_size (klass);
137         int i;
138
139         for (i = 0; i < klass->rank; ++i)
140                 size *= array->bounds [i].length;
141         memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
142
143 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
144 #define SWAP(n) {\
145         gint i; \
146         guint ## n tmp; \
147         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
148 \
149         for (i = 0; i < size; i += n/8, data++) { \
150                 tmp = read ## n (data); \
151                 *data = tmp; \
152         } \
153 }
154
155         printf ("Initialize array with elements of %s type\n", klass->element_class->name);
156
157         switch (klass->element_class->byval_arg.type) {
158         case MONO_TYPE_CHAR:
159         case MONO_TYPE_I2:
160         case MONO_TYPE_U2:
161                 SWAP (16);
162                 break;
163         case MONO_TYPE_I4:
164         case MONO_TYPE_U4:
165                 SWAP (32);
166                 break;
167         case MONO_TYPE_I8:
168         case MONO_TYPE_U8:
169                 SWAP (64);
170                 break;
171         }
172 #endif
173 }
174
175 static MonoObject *
176 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
177 {
178         return mono_object_clone (this);
179 }
180
181 static MonoObject *
182 ves_icall_app_get_cur_domain ()
183 {
184         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
185
186         return mono_object_new (klass);
187 }
188
189 static void
190 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
191 {
192         mtype->type = &obj->klass->byval_arg;
193 }
194
195 static gint32
196 ves_icall_get_data_chunk (MonoReflectionAssemblyBuilder *assb, gint32 type, MonoArray *buf)
197 {
198         int count;
199
200         if (type == 0) { /* get the header */
201                 count = mono_image_get_header (assb, (char*)buf->vector, buf->bounds->length);
202                 if (count != -1)
203                         return count;
204         } else {
205                 MonoDynamicAssembly *ass = assb->dynamic_assembly;
206                 char *p = mono_array_addr (buf, char, 0);
207                 count = ass->code.index + ass->meta_size;
208                 if (count > buf->bounds->length)
209                         return 0;
210                 memcpy (p, ass->code.data, ass->code.index);
211                 memcpy (p + ass->code.index, ass->assembly.image->raw_metadata, ass->meta_size);
212                 return count;
213         }
214         
215         return 0;
216 }
217
218 static MonoReflectionType*
219 ves_icall_type_from_name (MonoString *name)
220 {
221         MonoClass *klass;
222         gchar *n, *namespace, *str;
223         char* byref, *isarray;
224         guint rank;
225         
226         str = namespace = mono_string_to_utf8 (name);
227         /*g_print ("requested type %s\n", str);*/
228
229         n = strrchr (str, '.');
230         byref = strrchr (str, '&');
231         if (byref)
232                 *byref = 0;
233         isarray = strrchr (str, '[');
234         if (isarray) {
235                 rank = 1;
236                 *isarray = 0;
237                 while (*isarray) {
238                         if (*isarray == ',')
239                                 rank++;
240                         if (*isarray == ']')
241                                 break;
242                         ++isarray;
243                 }
244         }
245         if (n) {
246                 *n = 0;
247                 ++n;
248         } else {
249                 namespace = "";
250                 n = str;
251         }
252         klass = mono_class_from_name (mono_defaults.corlib, namespace, n);
253         g_free (str);
254         if (!klass)
255                 return NULL;
256         mono_class_init (klass);
257         if (isarray)
258                 klass = mono_array_class_get (klass, rank);
259         
260         if (byref)
261                 return mono_type_get_object (&klass->this_arg);
262         else
263                 return mono_type_get_object (&klass->byval_arg);
264 }
265
266 static MonoReflectionType*
267 ves_icall_type_from_handle (MonoType *handle)
268 {
269         mono_class_init (handle->data.klass);
270         return mono_type_get_object (handle);
271 }
272
273 static guint32
274 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c)
275 {
276         MonoClass *klass;
277         MonoClass *klassc;
278
279         g_assert (type != NULL);
280         
281         if (!c) /* FIXME: dont know what do do here */
282                 return 0;
283
284         while (!type->type) { /* FIXME: hack for TypeBuilder */
285                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)type;
286                 type = tb->parent;
287         }
288
289         while (!c->type) { /* FIXME: hack for TypeBuilder */
290                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)c;
291                 c = tb->parent;
292         }
293
294         klass = mono_class_from_mono_type (type->type);
295         klassc = mono_class_from_mono_type (c->type);
296
297         /* cut&paste from mono_object_isinst (): keep in sync */
298         if (klassc->flags & TYPE_ATTRIBUTE_INTERFACE) {
299                 if ((klassc->interface_id <= klass->max_interface_id) &&
300                     klass->interface_offsets [klassc->interface_id])
301                         return 1;
302         } else {
303                 if ((klass->baseval - klassc->baseval) <= klassc->diffval)
304                         return 1;
305         }
306         return 0;
307 }
308
309 static guint32
310 ves_icall_get_attributes (MonoReflectionType *type)
311 {
312         MonoClass *klass = mono_class_from_mono_type (type->type);
313
314         return klass->flags;
315 }
316
317 static void
318 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
319 {
320         info->parent = mono_type_get_object (&method->klass->byval_arg);
321         info->ret = mono_type_get_object (method->signature->ret);
322         info->name = mono_string_new (method->name);
323         info->attrs = method->flags;
324         info->implattrs = method->iflags;
325 }
326
327 static MonoArray*
328 ves_icall_get_parameter_info (MonoMethod *method) {
329         MonoArray *res;
330         MonoClass *oklass;
331         MonoReflectionParameter** args;
332         int i;
333
334         args = mono_param_get_objects (method);
335         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
336         res = mono_array_new (oklass, method->signature->param_count);
337         for (i = 0; i < method->signature->param_count; ++i) {
338                 mono_array_set (res, gpointer, i, args [i]);
339         }
340         return res;
341 }
342
343 static void
344 ves_icall_get_field_info (MonoReflectionField *field, MonoFieldInfo *info)
345 {
346         info->parent = mono_type_get_object (&field->klass->byval_arg);
347         info->type = mono_type_get_object (field->field->type);
348         info->name = mono_string_new (field->field->name);
349         info->attrs = field->field->type->attrs;
350 }
351
352 static void
353 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info)
354 {
355         info->parent = mono_type_get_object (&property->klass->byval_arg);
356         info->name = mono_string_new (property->property->name);
357         info->attrs = property->property->attrs;
358         info->get = property->property->get ? mono_method_get_object (property->property->get): NULL;
359         info->set = property->property->set ? mono_method_get_object (property->property->set): NULL;
360         /* 
361          * There may be other methods defined for properties, though, it seems they are not exposed 
362          * in the reflection API 
363          */
364 }
365
366 static void
367 ves_icall_get_type_info (MonoType *type, MonoTypeInfo *info)
368 {
369         MonoClass *class = mono_class_from_mono_type (type);
370         MonoClass *parent;
371         MonoArray *intf;
372         int ninterf, i;
373         
374         info->parent = class->parent ? mono_type_get_object (&class->parent->byval_arg): NULL;
375         info->name = mono_string_new (class->name);
376         info->name_space = mono_string_new (class->name_space);
377         info->attrs = class->flags;
378         info->rank = class->rank;
379         info->assembly = NULL; /* FIXME */
380         if (class->enumtype)
381                 info->etype = mono_type_get_object (class->enum_basetype);
382         else if (class->element_class)
383                 info->etype = mono_type_get_object (&class->element_class->byval_arg);
384         else
385                 info->etype = NULL;
386
387         ninterf = 0;
388         for (parent = class; parent; parent = parent->parent) {
389                 ninterf += parent->interface_count;
390         }
391         intf = mono_array_new (mono_defaults.monotype_class, ninterf);
392         ninterf = 0;
393         for (parent = class; parent; parent = parent->parent) {
394                 for (i = 0; i < parent->interface_count; ++i) {
395                         mono_array_set (intf, gpointer, ninterf, mono_type_get_object (&parent->interfaces [i]->byval_arg));
396                         ++ninterf;
397                 }
398         }
399         info->interfaces = intf;
400 }
401
402 static void
403 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
404 {
405         MonoClass *enumc = mono_class_from_mono_type (type->type);
406         guint i, j, nvalues, crow;
407         MonoClassField *field;
408         
409         info->utype = mono_type_get_object (enumc->enum_basetype);
410         nvalues = enumc->field.count - 1;
411         info->names = mono_array_new (mono_defaults.string_class, nvalues);
412         info->values = mono_array_new (mono_class_from_mono_type (enumc->enum_basetype), nvalues);
413         
414         for (i = 0, j = 0; i < enumc->field.count; ++i) {
415                 field = &enumc->fields [i];
416                 if (strcmp ("value__", field->name) == 0)
417                         continue;
418                 mono_array_set (info->names, gpointer, j, mono_string_new (field->name));
419                 if (!field->data) {
420                         crow = mono_metadata_get_constant_index (enumc->image, MONO_TOKEN_FIELD_DEF | (i+enumc->field.first+1));
421                         crow = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_VALUE);
422                         /* 1 is the length of the blob */
423                         field->data = 1 + mono_metadata_blob_heap (enumc->image, crow);
424                 }
425                 switch (enumc->enum_basetype->type) {
426                 case MONO_TYPE_U1:
427                 case MONO_TYPE_I1:
428                         mono_array_set (info->values, gchar, j, *field->data);
429                         break;
430                 case MONO_TYPE_CHAR:
431                 case MONO_TYPE_U2:
432                 case MONO_TYPE_I2:
433                         mono_array_set (info->values, gint16, j, read16 (field->data));
434                         break;
435                 case MONO_TYPE_U4:
436                 case MONO_TYPE_I4:
437                         mono_array_set (info->values, gint32, j, read32 (field->data));
438                         break;
439                 case MONO_TYPE_U8:
440                 case MONO_TYPE_I8:
441                         mono_array_set (info->values, gint64, j, read64 (field->data));
442                         break;
443                 default:
444                         g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
445                 }
446                 ++j;
447         }
448 }
449
450 static MonoMethod*
451 search_method (MonoReflectionType *type, char *name, guint32 flags, MonoArray *args)
452 {
453         MonoClass *klass;
454         MonoMethod *m;
455         MonoReflectionType *paramt;
456         int i, j;
457
458         klass = mono_class_from_mono_type (type->type);
459         while (klass) {
460                 for (i = 0; i < klass->method.count; ++i) {
461                         m = klass->methods [i];
462                         if (!((m->flags & flags) == flags))
463                                 continue;
464                         if (strcmp(m->name, name))
465                                 continue;
466                         if (m->signature->param_count != mono_array_length (args))
467                                 continue;
468                         for (j = 0; j < m->signature->param_count; ++j) {
469                                 paramt = mono_array_get (args, MonoReflectionType*, j);
470                                 if (!mono_metadata_type_equal (paramt->type, m->signature->params [j]))
471                                         break;
472                         }
473                         if (j == m->signature->param_count)
474                                 return m;
475                 }
476                 klass = klass->parent;
477         }
478         g_print ("Method %s::%s (%d) not found\n", klass->name, name, mono_array_length (args));
479         return NULL;
480 }
481
482 static MonoReflectionMethod*
483 ves_icall_get_constructor (MonoReflectionType *type, MonoArray *args)
484 {
485         MonoMethod *m;
486
487         m = search_method (type, ".ctor", METHOD_ATTRIBUTE_RT_SPECIAL_NAME, args);
488         if (m)
489                 return mono_method_get_object (m);
490         return NULL;
491 }
492
493 static MonoReflectionMethod*
494 ves_icall_get_method (MonoReflectionType *type, MonoString *name, MonoArray *args)
495 {
496         MonoMethod *m;
497         char *n = mono_string_to_utf8 (name);
498
499         m = search_method (type, n, 0, args);
500         g_free (n);
501         if (m)
502                 return mono_method_get_object (m);
503         return NULL;
504 }
505
506 static MonoProperty*
507 search_property (MonoClass *klass, char* name, MonoArray *args) {
508         int i;
509         MonoProperty *p;
510
511         /* FIXME: handle args */
512         for (i = 0; i < klass->property.count; ++i) {
513                 p = &klass->properties [i];
514                 if (strcmp (p->name, name) == 0)
515                         return p;
516         }
517         return NULL;
518 }
519
520 static MonoReflectionProperty*
521 ves_icall_get_property (MonoReflectionType *type, MonoString *name, MonoArray *args)
522 {
523         MonoProperty *p;
524         MonoClass *class = mono_class_from_mono_type (type->type);
525         char *n = mono_string_to_utf8 (name);
526
527         p = search_property (class, n, args);
528         g_free (n);
529         if (p)
530                 return mono_property_get_object (class, p);
531         return NULL;
532 }
533
534 enum {
535         BFLAGS_IgnoreCase = 1,
536         BFLAGS_DeclaredOnly = 2,
537         BFLAGS_Instance = 4,
538         BFLAGS_Static = 8,
539         BFLAGS_Public = 0x10,
540         BFLAGS_NonPublic = 0x20,
541         BFLAGS_InvokeMethod = 0x100,
542         BFLAGS_CreateInstance = 0x200,
543         BFLAGS_GetField = 0x400,
544         BFLAGS_SetField = 0x800,
545         BFLAGS_GetProperty = 0x1000,
546         BFLAGS_SetProperty = 0x2000,
547         BFLAGS_ExactBinding = 0x10000,
548         BFLAGS_SuppressChangeType = 0x20000,
549         BFLAGS_OptionalParamBinding = 0x40000
550 };
551
552
553 /*
554  * Note: the filter is applied from within corlib.
555  */
556 static MonoArray*
557 ves_icall_type_find_members (MonoReflectionType *type, guint32 membertypes, guint32 bflags)
558 {
559         GSList *l = NULL, *tmp;
560         MonoClass *startklass, *klass;
561         MonoArray *res;
562         MonoMethod *method;
563         MonoObject *member;
564         int i, is_ctor, len, match;
565
566         klass = startklass = mono_class_from_mono_type (type->type);
567
568         /* FIXME: check the bindingflags */
569 handle_parent:  
570         if (membertypes & (1|8)) { /* constructors and methods */
571                 for (i = 0; i < klass->method.count; ++i) {
572                         match = 0;
573                         method = klass->methods [i];
574                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
575                                 if (bflags & BFLAGS_Public)
576                                         match++;
577                         } else {
578                                 if (bflags & BFLAGS_NonPublic)
579                                         match++;
580                         }
581                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
582                                 if (bflags & BFLAGS_Static)
583                                         match++;
584                         } else {
585                                 if (bflags & BFLAGS_Instance)
586                                         match++;
587                         }
588
589                         if (!match)
590                                 continue;
591                         member = (MonoObject*)mono_method_get_object (method);
592                         
593                         is_ctor = strcmp (method->name, ".ctor") == 0 ||
594                                         strcmp (method->name, ".cctor") == 0;
595                         if (is_ctor && (membertypes & 1)) {
596                                 l = g_slist_prepend (l, member);
597                                 continue;
598                         }
599                         if (!is_ctor && (membertypes & 8)) {
600                                 l = g_slist_prepend (l, member);
601                         }
602                 }
603         }
604         if (membertypes & 4) { /* fields */
605                 MonoClassField *field;
606                 for (i = 0; i < klass->field.count; ++i) {
607                         match = 0;
608                         field = &klass->fields [i];
609                         if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
610                                 if (bflags & BFLAGS_Public)
611                                         match++;
612                         } else {
613                                 if (bflags & BFLAGS_NonPublic)
614                                         match++;
615                         }
616                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
617                                 if (bflags & BFLAGS_Static)
618                                         match++;
619                         } else {
620                                 if (bflags & BFLAGS_Instance)
621                                         match++;
622                         }
623
624                         if (!match)
625                                 continue;
626                         member = (MonoObject*)mono_field_get_object (klass, field);
627                         l = g_slist_prepend (l, member);
628                 }
629         }
630         if (membertypes & 16) { /* properties */
631                 MonoProperty *prop;
632                 for (i = 0; i < klass->property.count; ++i) {
633                         match = 0;
634                         prop = &klass->properties [i];
635                         /* FIXME: handle bflags */
636                         l = g_slist_prepend (l, mono_property_get_object (klass, prop));
637                 }
638         }
639         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
640                 goto handle_parent;
641         len = g_slist_length (l);
642         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MemberInfo");
643         res = mono_array_new (klass, len);
644         i = 0;
645         tmp = l;
646         for (; tmp; tmp = tmp->next, ++i)
647                 mono_array_set (res, gpointer, i, tmp->data);
648         g_slist_free (l);
649         return res;
650 }
651
652 static gpointer
653 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr)
654 {
655         return (gpointer)(*(int *)ptr);
656 }
657
658 static MonoString*
659 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
660 {
661         return mono_string_new ((char *)ptr);
662 }
663
664 static MonoReflectionAssembly*
665 ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *assName, MonoObject *evidence)
666 {
667         /* FIXME : examine evidence? */
668         char *name = mono_string_to_utf8 (assName);
669         enum MonoImageOpenStatus status = MONO_IMAGE_OK;
670         MonoAssembly *ass = mono_assembly_open (name, NULL, &status);
671
672         if (!ass)
673                 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.IO", "FileNotFoundException"));
674
675         return mono_assembly_get_object (ass);
676 }
677
678 static MonoReflectionType*
679 ves_icall_System_Reflection_Assembly_GetType (MonoReflectionAssembly *assembly, MonoString *type) /* , char throwOnError, char ignoreCase) */
680 {
681         /* FIXME : use throwOnError and ignoreCase */
682         gchar *name, *namespace, *str;
683         char *byref, *isarray;
684         guint rank;
685         MonoClass *klass;
686
687         str = namespace = mono_string_to_utf8 (type);
688         /*g_print ("requested type %s\n", str);*/
689
690         name = strrchr (str, '.');
691         byref = strrchr (str, '&');
692         if (byref)
693                 *byref = 0;
694         isarray = strrchr (str, '[');
695         if (isarray) {
696                 rank = 1;
697                 *isarray = 0;
698                 while (*isarray) {
699                         if (*isarray == ',')
700                                 rank++;
701                         if (*isarray == ']')
702                                 break;
703                         ++isarray;
704                 }
705         }
706
707         if (name) {
708                 *name = 0;
709                 ++name;
710         } else {
711                 namespace = "";
712                 name = str;
713         }
714
715         klass = mono_class_from_name (assembly->assembly->image, namespace, name);
716         g_free (str);
717         if (!klass)
718                 return NULL;
719         if (!klass->inited)
720                 mono_class_init (klass);
721
722         if (isarray) {
723                 klass = mono_array_class_get (klass, rank);
724                 mono_class_init (klass);
725                 /*g_print ("got array class %s [%d] (0x%x)\n", klass->element_class->name, klass->rank, klass->this_arg.type);*/
726         }
727
728         if (byref)
729                 return mono_type_get_object (&klass->this_arg);
730         else
731                 return mono_type_get_object (&klass->byval_arg);
732 }
733
734 static MonoString *
735 ves_icall_System_MonoType_assQualifiedName (MonoReflectionType *object)
736 {
737         /* FIXME : real rules are more complicated (internal classes,
738           reference types, array types, etc. */
739         MonoString *res;
740         gchar *fullname;
741         MonoClass *klass;
742         char *append = NULL;
743
744         switch (object->type->type) {
745         case MONO_TYPE_SZARRAY:
746                 klass = object->type->data.type->data.klass;
747                 append = "[]";
748                 break;
749         default:
750                 klass = object->type->data.klass;
751                 break;
752         }
753
754         fullname = g_strconcat (klass->name_space, ".",
755                                    klass->name, ",",
756                                    klass->image->assembly_name, append, NULL);
757         res = mono_string_new (fullname);
758         g_free (fullname);
759
760         return res;
761 }
762
763 static MonoString *
764 ves_icall_System_PAL_GetCurrentDirectory (MonoObject *object)
765 {
766         MonoString *res;
767         gchar *path = g_get_current_dir ();
768         res = mono_string_new (path);
769         g_free (path);
770         return res;
771 }
772
773 /*
774  * Magic number to convert a time which is relative to
775  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
776  */
777 #define EPOCH_ADJUST    ((gint64)62135596800L)
778
779 static gint64
780 ves_icall_System_DateTime_GetNow ()
781 {
782         struct timeval tv;
783         gint64 res;
784
785         if (gettimeofday (&tv, NULL) == 0) {
786                 res = (((gint64)tv.tv_sec + EPOCH_ADJUST)* 1000000 + tv.tv_usec)*10;
787                 return res;
788         }
789
790         /* fixme: raise exception */
791         return 0;
792 }
793
794 static gpointer icall_map [] = {
795         /*
796          * System.Array
797          */
798         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
799         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
800         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
801         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
802         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
803         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
804
805         /*
806          * System.Object
807          */
808         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
809
810         /*
811          * System.String
812          */
813         "System.String::IsInterned", mono_string_is_interned,
814         "System.String::Intern", mono_string_intern,
815
816         /*
817          * System.AppDomain
818          */
819         "System.AppDomain::getCurDomain", ves_icall_app_get_cur_domain,
820
821         /*
822          * System.Decimal
823          */
824         "System.Decimal::decimal2UInt64", mono_decimal2UInt64,
825         "System.Decimal::decimal2Int64", mono_decimal2Int64,
826         "System.Decimal::double2decimal", mono_double2decimal, /* FIXME: wrong signature. */
827         "System.Decimal::decimalIncr", mono_decimalIncr,
828         "System.Decimal::decimalSetExponent", mono_decimalSetExponent,
829         "System.Decimal::decimal2double", mono_decimal2double,
830         "System.Decimal::decimalFloorAndTrunc", mono_decimalFloorAndTrunc,
831         "System.Decimal::decimalRound", mono_decimalRound,
832         "System.Decimal::decimalMult", mono_decimalMult,
833         "System.Decimal::decimalDiv", mono_decimalDiv,
834         "System.Decimal::decimalIntDiv", mono_decimalIntDiv,
835         "System.Decimal::decimalCompare", mono_decimalCompare,
836         "System.Decimal::string2decimal", mono_string2decimal,
837         "System.Decimal::decimal2string", mono_decimal2string,
838
839         /*
840          * ModuleBuilder
841          */
842         
843         /*
844          * AssemblyBuilder
845          */
846         "System.Reflection.Emit.AssemblyBuilder::getDataChunk", ves_icall_get_data_chunk,
847         "System.Reflection.Emit.AssemblyBuilder::getUSIndex", mono_image_insert_string,
848         "System.Reflection.Emit.AssemblyBuilder::getToken", mono_image_create_token,
849
850         /*
851          * Reflection stuff.
852          */
853         "System.Reflection.MonoMethodInfo::get_method_info", ves_icall_get_method_info,
854         "System.Reflection.MonoMethodInfo::get_parameter_info", ves_icall_get_parameter_info,
855         "System.Reflection.MonoFieldInfo::get_field_info", ves_icall_get_field_info,
856         "System.Reflection.MonoPropertyInfo::get_property_info", ves_icall_get_property_info,
857         "System.MonoEnumInfo::get_enum_info", ves_icall_get_enum_info,
858         
859         /*
860          * TypeBuilder
861          */
862         
863         /*
864          * MethodBuilder
865          */
866         
867         /*
868          * System.Type
869          */
870         "System.Type::internal_from_name", ves_icall_type_from_name,
871         "System.Type::internal_from_handle", ves_icall_type_from_handle,
872         "System.Type::get_constructor", ves_icall_get_constructor,
873         "System.Type::get_property", ves_icall_get_property,
874         "System.Type::get_method", ves_icall_get_method,
875         "System.Type::get_attributes", ves_icall_get_attributes,
876         "System.Type::type_is_subtype_of", ves_icall_type_is_subtype_of,
877         "System.Type::FindMembers", ves_icall_type_find_members,
878
879         /*
880          * System.Runtime.CompilerServices.RuntimeHelpers
881          */
882         "System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray", ves_icall_InitializeArray,
883         
884         /*
885          * System.Threading
886          */
887         "System.Threading.Thread::Thread_internal", ves_icall_System_Threading_Thread_Thread_internal,
888         "System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
889         "System.Threading.Thread::Sleep_internal", ves_icall_System_Threading_Thread_Sleep_internal,
890         "System.Threading.Thread::CurrentThread_internal", ves_icall_System_Threading_Thread_CurrentThread_internal,
891         "System.Threading.Thread::Join_internal", ves_icall_System_Threading_Thread_Join_internal,
892         "System.Threading.Thread::SlotHash_lookup", ves_icall_System_Threading_Thread_SlotHash_lookup,
893         "System.Threading.Thread::SlotHash_store", ves_icall_System_Threading_Thread_SlotHash_store,
894         "System.Threading.Monitor::Monitor_exit", ves_icall_System_Threading_Monitor_Monitor_exit,
895         "System.Threading.Monitor::Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner,
896         "System.Threading.Monitor::Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised,
897         "System.Threading.Monitor::Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse,
898         "System.Threading.Monitor::Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all,
899         "System.Threading.Monitor::Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter,
900         "System.Threading.Monitor::Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait,
901         "System.Threading.Mutex::CreateMutex_internal", ves_icall_System_Threading_Mutex_CreateMutex_internal,
902         "System.Threading.Mutex::ReleaseMutex_internal", ves_icall_System_Threading_Mutex_ReleaseMutex_internal,
903
904         /*
905          * System.Threading.WaitHandle
906          */
907         "System.Threading.WaitHandle::WaitAll_internal", ves_icall_System_Threading_WaitHandle_WaitAll_internal,
908         "System.Threading.WaitHandle::WaitAny_internal", ves_icall_System_Threading_WaitHandle_WaitAny_internal,
909         "System.Threading.WaitHandle::WaitOne_internal", ves_icall_System_Threading_WaitHandle_WaitOne_internal,
910
911         "System.Runtime.InteropServices.Marshal::ReadIntPtr", ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr,
912         "System.Runtime.InteropServices.Marshal::PtrToStringAuto", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto,
913
914         "System.Reflection.Assembly::LoadFrom", ves_icall_System_Reflection_Assembly_LoadFrom,
915         "System.Reflection.Assembly::GetType", ves_icall_System_Reflection_Assembly_GetType,
916
917         /*
918          * System.MonoType.
919          */
920         "System.MonoType::assQualifiedName", ves_icall_System_MonoType_assQualifiedName,
921         "System.MonoType::type_from_obj", mono_type_type_from_obj,
922         "System.MonoType::get_type_info", ves_icall_get_type_info,
923
924         "System.PAL.OpSys::GetCurrentDirectory", ves_icall_System_PAL_GetCurrentDirectory,
925
926         /*
927          * System.PAL.OpSys I/O Services
928          */
929         "System.PAL.OpSys::GetStdHandle", ves_icall_System_PAL_OpSys_GetStdHandle,
930         "System.PAL.OpSys::ReadFile", ves_icall_System_PAL_OpSys_ReadFile,
931         "System.PAL.OpSys::WriteFile", ves_icall_System_PAL_OpSys_WriteFile,
932         "System.PAL.OpSys::SetLengthFile", ves_icall_System_PAL_OpSys_SetLengthFile,
933         "System.PAL.OpSys::OpenFile", ves_icall_System_PAL_OpSys_OpenFile,
934         "System.PAL.OpSys::CloseFile", ves_icall_System_PAL_OpSys_CloseFile,
935         "System.PAL.OpSys::SeekFile", ves_icall_System_PAL_OpSys_SeekFile,
936         "System.PAL.OpSys::DeleteFile", ves_icall_System_PAL_OpSys_DeleteFile,
937         "System.PAL.OpSys::ExistsFile", ves_icall_System_PAL_OpSys_ExistsFile,
938         "System.PAL.OpSys::GetFileTime", ves_icall_System_PAL_OpSys_GetFileTime,
939         "System.PAL.OpSys::SetFileTime", ves_icall_System_PAL_OpSys_SetFileTime,
940
941         /*
942          * System.Char
943          */
944         "System.Char::GetNumericValue", ves_icall_System_Char_GetNumericValue,
945         "System.Char::GetUnicodeCategory", ves_icall_System_Char_GetUnicodeCategory,
946         "System.Char::IsControl", ves_icall_System_Char_IsControl,
947         "System.Char::IsDigit", ves_icall_System_Char_IsDigit,
948         "System.Char::IsLetter", ves_icall_System_Char_IsLetter,
949         "System.Char::IsLower", ves_icall_System_Char_IsLower,
950         "System.Char::IsUpper", ves_icall_System_Char_IsUpper,
951         "System.Char::IsNumber", ves_icall_System_Char_IsNumber,
952         "System.Char::IsPunctuation", ves_icall_System_Char_IsPunctuation,
953         "System.Char::IsSeparator", ves_icall_System_Char_IsSeparator,
954         "System.Char::IsSurrogate", ves_icall_System_Char_IsSurrogate,
955         "System.Char::IsSymbol", ves_icall_System_Char_IsSymbol,
956         "System.Char::IsWhiteSpace", ves_icall_System_Char_IsWhiteSpace,
957         "System.Char::ToLower", ves_icall_System_Char_ToLower,
958         "System.Char::ToUpper", ves_icall_System_Char_ToUpper,
959
960         "System.Text.Encoding::IConvNewEncoder", ves_icall_iconv_new_encoder,
961         "System.Text.Encoding::IConvNewDecoder", ves_icall_iconv_new_decoder,
962         "System.Text.Encoding::IConvReset", ves_icall_iconv_reset,
963         "System.Text.Encoding::IConvGetByteCount", ves_icall_iconv_get_byte_count,
964         "System.Text.Encoding::IConvGetBytes", ves_icall_iconv_get_bytes,
965         "System.Text.Encoding::IConvGetCharCount", ves_icall_iconv_get_char_count,
966         "System.Text.Encoding::IConvGetChars", ves_icall_iconv_get_chars,
967
968         "System.DateTime::GetNow", ves_icall_System_DateTime_GetNow,
969         /*
970          * add other internal calls here
971          */
972         NULL, NULL
973 };
974
975 void
976 mono_init_icall ()
977 {
978         char *n;
979         int i = 0;
980
981         while ((n = icall_map [i])) {
982                 mono_add_internal_call (n, icall_map [i+1]);
983                 i += 2;
984         }
985        
986 }
987
988