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