Fri Nov 2 19:06:54 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
19 static MonoObject *
20 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
21 {
22         MonoClass *ac, *ic;
23         MonoArray *ao, *io;
24         gint32 i, pos, *ind, esize;
25         gpointer *ea;
26
27         io = (MonoArray *)idxs;
28         ic = (MonoClass *)io->obj.klass;
29         
30         ao = (MonoArray *)this;
31         ac = (MonoClass *)ao->obj.klass;
32
33         g_assert (ic->rank == 1);
34         g_assert (io->bounds [0].length == ac->rank);
35
36         ind = (guint32 *)io->vector;
37
38         pos = ind [0] - ao->bounds [0].lower_bound;
39         for (i = 1; i < ac->rank; i++)
40                 pos = pos*ao->bounds [i].length + ind [i] - 
41                         ao->bounds [i].lower_bound;
42
43         esize = mono_array_element_size (ac);
44         ea = ao->vector + (pos * esize);
45
46         if (ac->element_class->valuetype)
47                 return mono_value_box (ac->element_class, ea);
48         else
49                 return *ea;
50 }
51
52 static void 
53 ves_icall_System_Array_SetValue (MonoObject *this, MonoObject *value,
54                                  MonoObject *idxs)
55 {
56         MonoArray *ao, *io, *vo;
57         MonoClass *ac, *ic, *vc;
58         gint32 i, pos, *ind, esize;
59         gpointer *ea;
60
61         vo = (MonoArray *)value;
62         vc = (MonoClass *)vo->obj.klass;
63
64         io = (MonoArray *)idxs;
65         ic = (MonoClass *)io->obj.klass;
66         
67         ao = (MonoArray *)this;
68         ac = (MonoClass *)ao->obj.klass;
69
70         g_assert (ic->rank == 1);
71         g_assert (io->bounds [0].length == ac->rank);
72         g_assert (ac->element_class == vo->obj.klass);
73
74         ind = (guint32 *)io->vector;
75
76         pos = ind [0] - ao->bounds [0].lower_bound;
77         for (i = 1; i < ac->rank; i++)
78                 pos = pos*ao->bounds [i].length + ind [i] - 
79                         ao->bounds [i].lower_bound;
80
81         esize = mono_array_element_size (ac);
82         ea = ao->vector + (pos * esize);
83
84         if (ac->element_class->valuetype) {
85                 g_assert (vc->valuetype);
86
87                 memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
88         } else
89                 *ea = (gpointer)vo;
90
91 }
92
93 static void 
94 ves_icall_array_ctor (MonoObject *this, gint32 n1, ...)
95 {
96         va_list ap;
97         MonoArray *ao;
98         MonoClass *ac;
99         gint32 i, s, len, esize;
100
101         va_start (ap, n1);
102
103         ao = (MonoArray *)this;
104         ac = (MonoClass *)this->klass;
105
106         g_assert (ac->rank >= 1);
107
108         ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
109
110         len = n1;
111         ao->bounds [0].length = n1;
112         for (i = 1; i < ac->rank; i++) {
113                 s = va_arg (ap, gint32);
114                 len *= s;
115                 ao->bounds [i].length = s;
116         }
117
118         esize = mono_array_element_size (ac);
119         ao->vector = g_malloc0 (len * esize);
120 }
121
122 static void 
123 ves_icall_array_bound_ctor (MonoObject *this, gint32 n1, ...)
124 {
125         va_list ap;
126         MonoArray *ao;
127         MonoClass *ac;
128         gint32 i, s, len, esize;
129
130         va_start (ap, n1);
131
132         ao = (MonoArray *)this;
133         ac = (MonoClass *)this->klass;
134
135         g_assert (ac->rank >= 1);
136
137         ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
138
139         ao->bounds [0].lower_bound = n1;
140         for (i = 1; i < ac->rank; i++)
141                 ao->bounds [i].lower_bound = va_arg (ap, gint32);
142
143         len = va_arg (ap, gint32);
144         ao->bounds [0].length = len;
145         for (i = 1; i < ac->rank; i++) {
146                 s = va_arg (ap, gint32);
147                 len *= s;
148                 ao->bounds [i].length = s;
149         }
150
151         esize = mono_array_element_size (ac);
152         ao->vector = g_malloc0 (len * esize);
153 }
154
155 static void
156 ves_icall_System_Array_CreateInstance ()
157 {
158         g_warning ("not implemented");
159         g_assert_not_reached ();
160 }
161
162
163 static gint32 
164 ves_icall_System_Array_GetRank (MonoObject *this)
165 {
166         return this->klass->rank;
167 }
168
169 static gint32
170 ves_icall_System_Array_GetLength (MonoObject *this, gint32 dimension)
171 {
172         return ((MonoArray *)this)->bounds [dimension].length;
173 }
174
175 static gint32
176 ves_icall_System_Array_GetLowerBound (MonoObject *this, gint32 dimension)
177 {
178         return ((MonoArray *)this)->bounds [dimension].lower_bound;
179 }
180
181 static MonoObject *
182 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
183 {
184         return mono_object_clone (this);
185 }
186
187 static MonoObject *
188 ves_icall_app_get_cur_domain ()
189 {
190         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
191
192         return mono_object_new (klass);
193 }
194
195 static MonoObject *
196 my_mono_new_object (MonoClass *klass, gpointer data)
197 {
198         MonoClassField *field;
199         MonoObject *res = mono_object_new (klass);
200         gpointer *slot;
201
202         field = mono_class_get_field_from_name (klass, "_impl");
203         slot = (gpointer*)((char*)res + field->offset);
204         *slot = data;
205         return res;
206 }
207
208 static gint32
209 ves_icall_get_data_chunk (MonoReflectionAssemblyBuilder *assb, gint32 type, MonoArray *buf)
210 {
211         int count;
212
213         if (type == 0) { /* get the header */
214                 count = mono_image_get_header (assb, buf->vector, buf->bounds->length);
215                 if (count != -1)
216                         return count;
217         } else {
218                 MonoDynamicAssembly *ass = assb->dynamic_assembly;
219                 count = ass->code.index + ass->meta_size;
220                 if (count > buf->bounds->length)
221                         return 0;
222                 memcpy (buf->vector, ass->code.data, ass->code.index);
223                 memcpy (buf->vector + ass->code.index, ass->assembly.image->raw_metadata, ass->meta_size);
224                 return count;
225         }
226         
227         return 0;
228 }
229
230 static MonoObject*
231 ves_icall_type_from_name (MonoObject *name)
232 {
233         return NULL;
234 }
235
236 static MonoObject*
237 ves_icall_type_from_handle (gpointer handle)
238 {
239         return my_mono_new_object (mono_defaults.type_class, handle);
240 }
241
242 static gpointer icall_map [] = {
243         /*
244          * System.Array
245          */
246         "__array_ctor",                   ves_icall_array_ctor,
247         "__array_bound_ctor",             ves_icall_array_bound_ctor,
248         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
249         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
250         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
251         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
252         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
253         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
254
255         /*
256          * System.Object
257          */
258         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
259
260         /*
261          * System.String
262          */
263         "System.String::IsInterned", mono_string_is_interned,
264         "System.String::Intern", mono_string_intern,
265
266         /*
267          * System.AppDomain
268          */
269         "System.AppDomain::getCurDomain", ves_icall_app_get_cur_domain,
270
271         /*
272          * ModuleBuilder
273          */
274         
275         /*
276          * AssemblyBuilder
277          */
278         "System.Reflection.Emit.AssemblyBuilder::getDataChunk", ves_icall_get_data_chunk,
279         
280         /*
281          * TypeBuilder
282          */
283         
284         /*
285          * MethodBuilder
286          */
287         
288         /*
289          * System.Type
290          */
291         "System.Type::internal_from_name", ves_icall_type_from_name,
292         "System.Type::internal_from_handle", ves_icall_type_from_handle,
293         
294         /*
295          * System.Threading
296          */
297         "System.Threading.Thread::Thread_internal", ves_icall_System_Threading_Thread_Thread_internal,
298         "System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
299         "System.Threading.Thread::Sleep_internal", ves_icall_System_Threading_Thread_Sleep_internal,
300         "System.Threading.Thread::Schedule_internal", ves_icall_System_Threading_Thread_Schedule_internal,
301         "System.Threading.Thread::CurrentThread_internal", ves_icall_System_Threading_Thread_CurrentThread_internal,
302         "System.Threading.Thread::Join_internal", ves_icall_System_Threading_Thread_Join_internal,
303         "System.Threading.Thread::DataSlot_register", ves_icall_System_Threading_Thread_DataSlot_register,
304         "System.Threading.Thread::DataSlot_store", ves_icall_System_Threading_Thread_DataSlot_store,
305         "System.Threading.Thread::DataSlot_retrieve", ves_icall_System_Threading_Thread_DataSlot_retrieve,
306         /* Not in the System.Threading namespace, but part of the same code */
307         "System.LocalDataStoreSlot::DataSlot_unregister", ves_icall_System_LocalDataStoreSlot_DataSlot_unregister,
308         "System.Threading.Monitor::Monitor_enter", ves_icall_System_Threading_Monitor_Monitor_enter,
309         "System.Threading.Monitor::Monitor_exit", ves_icall_System_Threading_Monitor_Monitor_exit,
310         "System.Threading.Monitor::Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner,
311         "System.Threading.Monitor::Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised,
312         "System.Threading.Monitor::Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse,
313         "System.Threading.Monitor::Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all,
314         "System.Threading.Monitor::Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter,
315         "System.Threading.Monitor::Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait,
316
317         /*
318          * add other internal calls here
319          */
320         NULL, NULL
321 };
322
323 void
324 mono_init_icall ()
325 {
326         char *n;
327         int i = 0;
328
329         while ((n = icall_map [i])) {
330                 mono_add_internal_call (n, icall_map [i+1]);
331                 i += 2;
332         }
333        
334 }
335
336