2001-12-04 Dietmar Maurer <dietmar@ximian.com>
[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 "decimal.h"
22
23 static MonoObject *
24 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
25 {
26         MonoClass *ac, *ic;
27         MonoArray *ao, *io;
28         gint32 i, pos, *ind, esize;
29         gpointer *ea;
30
31         io = (MonoArray *)idxs;
32         ic = (MonoClass *)io->obj.klass;
33         
34         ao = (MonoArray *)this;
35         ac = (MonoClass *)ao->obj.klass;
36
37         g_assert (ic->rank == 1);
38         g_assert (io->bounds [0].length == ac->rank);
39
40         ind = (guint32 *)io->vector;
41
42         pos = ind [0] - ao->bounds [0].lower_bound;
43         for (i = 1; i < ac->rank; i++)
44                 pos = pos*ao->bounds [i].length + ind [i] - 
45                         ao->bounds [i].lower_bound;
46
47         esize = mono_array_element_size (ac);
48         ea = (gpointer*)((char*)ao->vector + (pos * esize));
49
50         if (ac->element_class->valuetype)
51                 return mono_value_box (ac->element_class, ea);
52         else
53                 return *ea;
54 }
55
56 static void 
57 ves_icall_System_Array_SetValue (MonoObject *this, MonoObject *value,
58                                  MonoObject *idxs)
59 {
60         MonoArray *ao, *io, *vo;
61         MonoClass *ac, *ic, *vc;
62         gint32 i, pos, *ind, esize;
63         gpointer *ea;
64
65         vo = (MonoArray *)value;
66         vc = (MonoClass *)vo->obj.klass;
67
68         io = (MonoArray *)idxs;
69         ic = (MonoClass *)io->obj.klass;
70         
71         ao = (MonoArray *)this;
72         ac = (MonoClass *)ao->obj.klass;
73
74         g_assert (ic->rank == 1);
75         g_assert (io->bounds [0].length == ac->rank);
76         g_assert (ac->element_class == vo->obj.klass);
77
78         ind = (guint32 *)io->vector;
79
80         pos = ind [0] - ao->bounds [0].lower_bound;
81         for (i = 1; i < ac->rank; i++)
82                 pos = pos*ao->bounds [i].length + ind [i] - 
83                         ao->bounds [i].lower_bound;
84
85         esize = mono_array_element_size (ac);
86         ea = (gpointer*)((char*)ao->vector + (pos * esize));
87
88         if (ac->element_class->valuetype) {
89                 g_assert (vc->valuetype);
90
91                 memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
92         } else
93                 *ea = (gpointer)vo;
94
95 }
96
97 static void
98 ves_icall_System_Array_CreateInstance ()
99 {
100         g_warning ("not implemented");
101         g_assert_not_reached ();
102 }
103
104
105 static gint32 
106 ves_icall_System_Array_GetRank (MonoObject *this)
107 {
108         return this->klass->rank;
109 }
110
111 static gint32
112 ves_icall_System_Array_GetLength (MonoObject *this, gint32 dimension)
113 {
114         return ((MonoArray *)this)->bounds [dimension].length;
115 }
116
117 static gint32
118 ves_icall_System_Array_GetLowerBound (MonoObject *this, gint32 dimension)
119 {
120         return ((MonoArray *)this)->bounds [dimension].lower_bound;
121 }
122
123 static void
124 ves_icall_InitializeArray (MonoArray *array, MonoClassField *field_handle)
125 {
126                 guint32 size = mono_array_element_size (((MonoObject*) array)->klass) * mono_array_length (array);
127                 /*
128                  * FIXME: ENOENDIAN: we need to byteswap as needed.
129                  */
130                 memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
131 }
132
133 static MonoObject *
134 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
135 {
136         return mono_object_clone (this);
137 }
138
139 static MonoObject *
140 ves_icall_app_get_cur_domain ()
141 {
142         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
143
144         return mono_object_new (klass);
145 }
146
147 static MonoReflectionType *
148 my_mono_new_mono_type (MonoType *type)
149 {
150         MonoReflectionType *res = (MonoReflectionType *)mono_object_new (mono_defaults.monotype_class);
151
152         res->type = type;
153         return res;
154 }
155
156 static void
157 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
158 {
159         mtype->type = &obj->klass->byval_arg;
160 }
161
162 static gint32
163 ves_icall_get_data_chunk (MonoReflectionAssemblyBuilder *assb, gint32 type, MonoArray *buf)
164 {
165         int count;
166
167         if (type == 0) { /* get the header */
168                 count = mono_image_get_header (assb, (char*)buf->vector, buf->bounds->length);
169                 if (count != -1)
170                         return count;
171         } else {
172                 MonoDynamicAssembly *ass = assb->dynamic_assembly;
173                 char *p = mono_array_addr (buf, char, 0);
174                 count = ass->code.index + ass->meta_size;
175                 if (count > buf->bounds->length)
176                         return 0;
177                 memcpy (p, ass->code.data, ass->code.index);
178                 memcpy (p + ass->code.index, ass->assembly.image->raw_metadata, ass->meta_size);
179                 return count;
180         }
181         
182         return 0;
183 }
184
185 static MonoObject*
186 ves_icall_type_from_name (MonoObject *name)
187 {
188         return NULL;
189 }
190
191 static MonoReflectionType*
192 ves_icall_type_from_handle (MonoType *handle)
193 {
194         return my_mono_new_mono_type (handle);
195 }
196
197 static gpointer
198 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr)
199 {
200         return (gpointer)(*(int *)ptr);
201 }
202
203 static MonoString*
204 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
205 {
206         return mono_string_new ((char *)ptr);
207 }
208
209 static MonoReflectionAssembly*
210 ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *assName, MonoObject *evidence)
211 {
212         /* FIXME : examine evidence? */
213         char *name = mono_string_to_utf8 (assName);
214         enum MonoImageOpenStatus status = MONO_IMAGE_OK;
215         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
216         MonoAssembly *ass = mono_assembly_open (name, NULL, &status);
217         MonoReflectionAssembly *res;
218
219         g_assert (ass != NULL);
220         g_assert (status == MONO_IMAGE_OK);
221
222         res = (MonoReflectionAssembly *)mono_object_new (klass);
223         res->assembly = ass;
224
225         g_free (name);
226
227         return res;
228 }
229
230 static MonoReflectionType*
231 ves_icall_System_Reflection_Assembly_GetType (MonoReflectionAssembly *assembly, MonoString *type) /* , char throwOnError, char ignoreCase) */
232 {
233         /* FIXME : use throwOnError and ignoreCase */
234         gchar *name, *namespace, **parts;
235         MonoClass *klass;
236         int j = 0;
237
238         name = mono_string_to_utf8 (type);
239
240         parts = g_strsplit (name, ".", 0);
241         g_free (name);
242
243         while (parts[j])
244                 j++;
245
246         name = parts[j-1];
247         parts[j-1] = NULL;
248         namespace = g_strjoinv (".", parts);
249         g_strfreev (parts);
250
251         klass = mono_class_from_name (assembly->assembly->image, namespace, name);
252         g_free (name);
253         g_free (namespace);
254         if (!klass)
255                 return NULL;
256         if (!klass->inited)
257                 mono_class_init (klass);
258
259         return my_mono_new_mono_type (&klass->byval_arg);
260 }
261
262 static MonoString *
263 ves_icall_System_MonoType_assQualifiedName (MonoReflectionType *object)
264 {
265         /* FIXME : real rules are more complicated (internal classes,
266           reference types, array types, etc. */
267         MonoString *res;
268         gchar *fullname;
269         MonoClass *klass;
270         char *append = NULL;
271
272         switch (object->type->type) {
273         case MONO_TYPE_SZARRAY:
274                 klass = object->type->data.type->data.klass;
275                 append = "[]";
276                 break;
277         default:
278                 klass = object->type->data.klass;
279                 break;
280         }
281
282         fullname = g_strconcat (klass->name_space, ".",
283                                    klass->name, ",",
284                                    klass->image->assembly_name, append, NULL);
285         res = mono_string_new (fullname);
286         g_free (fullname);
287
288         return res;
289 }
290
291 static MonoString *
292 ves_icall_System_PAL_GetCurrentDirectory (MonoObject *object)
293 {
294         MonoString *res;
295         gchar *path = g_get_current_dir ();
296         res = mono_string_new (path);
297         g_free (path);
298         return res;
299 }
300
301 static gint64
302 ves_icall_System_DateTime_GetNow ()
303 {
304         struct timeval tv;
305
306         // fixme: it seems that .Net has another base time than Unix??
307         if (gettimeofday (&tv, NULL) == 0) {
308                 return (gint64)tv.tv_sec * 1000000000 + tv.tv_usec*10;
309         }
310
311         
312         return 0;
313 }
314
315 static gpointer icall_map [] = {
316         /*
317          * System.Array
318          */
319         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
320         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
321         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
322         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
323         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
324         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
325
326         /*
327          * System.Object
328          */
329         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
330
331         /*
332          * System.String
333          */
334         "System.String::IsInterned", mono_string_is_interned,
335         "System.String::Intern", mono_string_intern,
336
337         /*
338          * System.AppDomain
339          */
340         "System.AppDomain::getCurDomain", ves_icall_app_get_cur_domain,
341
342         /*
343          * System.Decimal
344          */
345         "System.Decimal::decimal2UInt64", mono_decimal2UInt64,
346         "System.Decimal::decimal2Int64", mono_decimal2Int64,
347         "System.Decimal::double2decimal", mono_double2decimal, /* FIXME: wrong signature. */
348         "System.Decimal::decimalIncr", mono_decimalIncr,
349         "System.Decimal::decimalSetExponent", mono_decimalSetExponent,
350         "System.Decimal::decimal2double", mono_decimal2double,
351         "System.Decimal::decimalFloorAndTrunc", mono_decimalFloorAndTrunc,
352         "System.Decimal::decimalRound", mono_decimalRound,
353         "System.Decimal::decimalMult", mono_decimalMult,
354         "System.Decimal::decimalDiv", mono_decimalDiv,
355         "System.Decimal::decimalIntDiv", mono_decimalIntDiv,
356         "System.Decimal::decimalCompare", mono_decimalCompare,
357         "System.Decimal::string2decimal", mono_string2decimal,
358         "System.Decimal::decimal2string", mono_decimal2string,
359
360         /*
361          * ModuleBuilder
362          */
363         
364         /*
365          * AssemblyBuilder
366          */
367         "System.Reflection.Emit.AssemblyBuilder::getDataChunk", ves_icall_get_data_chunk,
368         "System.Reflection.Emit.AssemblyBuilder::getUSIndex", mono_image_insert_string,
369         
370         /*
371          * TypeBuilder
372          */
373         
374         /*
375          * MethodBuilder
376          */
377         
378         /*
379          * System.Type
380          */
381         "System.Type::internal_from_name", ves_icall_type_from_name,
382         "System.Type::internal_from_handle", ves_icall_type_from_handle,
383
384         /*
385          * System.Runtime.CompilerServices.RuntimeHelpers
386          */
387         "System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray", ves_icall_InitializeArray,
388         
389         /*
390          * System.Threading
391          */
392         "System.Threading.Thread::Thread_internal", ves_icall_System_Threading_Thread_Thread_internal,
393         "System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
394         "System.Threading.Thread::Sleep_internal", ves_icall_System_Threading_Thread_Sleep_internal,
395         "System.Threading.Thread::CurrentThread_internal", ves_icall_System_Threading_Thread_CurrentThread_internal,
396         "System.Threading.Thread::Join_internal", ves_icall_System_Threading_Thread_Join_internal,
397         "System.Threading.Thread::SlotHash_lookup", ves_icall_System_Threading_Thread_SlotHash_lookup,
398         "System.Threading.Thread::SlotHash_store", ves_icall_System_Threading_Thread_SlotHash_store,
399         "System.Threading.Monitor::Monitor_exit", ves_icall_System_Threading_Monitor_Monitor_exit,
400         "System.Threading.Monitor::Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner,
401         "System.Threading.Monitor::Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised,
402         "System.Threading.Monitor::Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse,
403         "System.Threading.Monitor::Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all,
404         "System.Threading.Monitor::Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter,
405         "System.Threading.Monitor::Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait,
406
407         "System.Runtime.InteropServices.Marshal::ReadIntPtr", ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr,
408         "System.Runtime.InteropServices.Marshal::PtrToStringAuto", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto,
409
410         "System.Reflection.Assembly::LoadFrom", ves_icall_System_Reflection_Assembly_LoadFrom,
411         "System.Reflection.Assembly::GetType", ves_icall_System_Reflection_Assembly_GetType,
412
413         /*
414          * System.MonoType.
415          */
416         "System.MonoType::assQualifiedName", ves_icall_System_MonoType_assQualifiedName,
417         "System.MonoType::type_from_obj", mono_type_type_from_obj,
418
419         "System.PAL.OpSys::GetCurrentDirectory", ves_icall_System_PAL_GetCurrentDirectory,
420         "System.DateTime::GetNow", ves_icall_System_DateTime_GetNow,
421         /*
422          * add other internal calls here
423          */
424         NULL, NULL
425 };
426
427 void
428 mono_init_icall ()
429 {
430         char *n;
431         int i = 0;
432
433         while ((n = icall_map [i])) {
434                 mono_add_internal_call (n, icall_map [i+1]);
435                 i += 2;
436         }
437        
438 }
439
440