Thu Oct 4 19:10:30 CEST 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         MonoArrayObject *ao, *io;
23         MonoArrayClass *ac, *ic;
24         gint32 i, pos, *ind, esize;
25         gpointer *ea;
26
27         io = (MonoArrayObject *)idxs;
28         ic = (MonoArrayClass *)io->obj.klass;
29         
30         ao = (MonoArrayObject *)this;
31         ac = (MonoArrayClass *)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         MonoArrayObject *ao, *io, *vo;
57         MonoArrayClass *ac, *ic, *vc;
58         gint32 i, pos, *ind, esize;
59         gpointer *ea;
60
61         vo = (MonoArrayObject *)value;
62         vc = (MonoArrayClass *)vo->obj.klass;
63
64         io = (MonoArrayObject *)idxs;
65         ic = (MonoArrayClass *)io->obj.klass;
66         
67         ao = (MonoArrayObject *)this;
68         ac = (MonoArrayClass *)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->klass.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         MonoArrayObject *ao;
98         MonoArrayClass *ac;
99         gint32 i, s, len, esize;
100
101         va_start (ap, n1);
102
103         ao = (MonoArrayObject *)this;
104         ac = (MonoArrayClass *)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         MonoArrayObject *ao;
127         MonoArrayClass *ac;
128         gint32 i, s, len, esize;
129
130         va_start (ap, n1);
131
132         ao = (MonoArrayObject *)this;
133         ac = (MonoArrayClass *)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 ((MonoArrayClass *)this->klass)->rank;
167 }
168
169 static gint32
170 ves_icall_System_Array_GetLength (MonoObject *this, gint32 dimension)
171 {
172         return ((MonoArrayObject *)this)->bounds [dimension].length;
173 }
174
175 static gint32
176 ves_icall_System_Array_GetLowerBound (MonoObject *this, gint32 dimension)
177 {
178         return ((MonoArrayObject *)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_new_object (klass);
193 }
194
195 static MonoObject *
196 my_mono_new_object (MonoClass *klass, gpointer data)
197 {
198         MonoClassField *field;
199         MonoObject *res = mono_new_object (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 gpointer
209 object_field_pointer (MonoObject *obj, char *name)
210 {
211         MonoClassField *field;
212         gpointer *slot;
213
214         field = mono_class_get_field_from_name (obj->klass, name);
215         slot = (gpointer*)((char*)obj + field->offset);
216         return *slot;
217 }
218
219 static gpointer
220 object_impl_pointer (MonoObject *obj)
221 {
222         return object_field_pointer (obj, "_impl");
223 }
224
225 static MonoObject *
226 ves_icall_app_define_assembly (MonoObject *appdomain, MonoObject *assembly_name, int access)
227 {
228         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "AssemblyBuilder");
229         MonoDynamicAssembly *ass = g_new0 (MonoDynamicAssembly, 1);
230         MonoClassField *field;
231         MonoObject *name;
232
233         field = mono_class_get_field_from_name (assembly_name->klass, "name");
234         name = *(MonoObject**)((char*)assembly_name + field->offset);
235
236         ass->name = mono_string_to_utf8 (name);
237
238         return my_mono_new_object (klass, ass);
239 }
240
241 static gint32
242 ves_icall_get_data_chunk (MonoObject *assb, gint32 type, MonoArrayObject *buf)
243 {
244         MonoDynamicAssembly *ass = object_impl_pointer (assb);
245         MonoObject *ep;
246         int count;
247         /*
248          * get some info from the object
249          */
250         ep = object_field_pointer (assb, "entry_point");
251         if (ep)
252                 ass->entry_point = object_impl_pointer (ep);
253         else
254                 ass->entry_point = 0;
255
256         if (type == 0) { /* get the header */
257                 count = mono_image_get_header (ass, buf->vector, buf->bounds->length);
258                 if (count != -1)
259                         return count;
260         } else {
261                 count = ass->code.index + ass->meta_size;
262                 if (count > buf->bounds->length)
263                         return 0;
264                 memcpy (buf->vector, ass->code.data, ass->code.index);
265                 memcpy (buf->vector + ass->code.index, ass->assembly.image->raw_metadata, ass->meta_size);
266                 return count;
267         }
268         
269         return 0;
270 }
271
272 static MonoObject *
273 ves_icall_define_module (MonoObject *assb, MonoObject *name, MonoObject *fname)
274 {
275         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "ModuleBuilder");
276         MonoModuleBuilder *mb = g_new0 (MonoModuleBuilder, 1);
277         MonoDynamicAssembly *ass = object_impl_pointer (assb);
278         ass->modules = g_list_prepend (ass->modules, mb);
279
280         mb->name = mono_string_to_utf8 (name);
281         mb->fname = mono_string_to_utf8 (fname);
282
283         return my_mono_new_object (klass, mb);
284 }
285
286 static MonoObject *
287 ves_icall_define_type (MonoObject *moduleb, MonoObject *name, int attrs)
288 {
289         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
290         MonoTypeBuilder *tb = g_new0 (MonoTypeBuilder, 1);
291         MonoModuleBuilder *mb = object_impl_pointer (moduleb);
292         char *nspace = mono_string_to_utf8 (name);
293         char *tname = strrchr (nspace, '.');
294         
295         if (tname) {
296                 *tname = 0;
297                 tname++;
298         } else {
299                 nspace = "";
300         }
301         
302         tb->name = tname;
303         tb->nspace = nspace;
304         tb->attrs = attrs;
305         mb->types = g_list_prepend (mb->types, tb);
306
307         return my_mono_new_object (klass, tb);
308 }
309
310 static MonoObject *
311 ves_icall_define_method (MonoObject *typeb, MonoObject *name, int attrs, int callconv, MonoObject *rettype, MonoArrayObject *paramtypes)
312 {
313         MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "MethodBuilder");
314         MonoMethodBuilder *mb = g_new0 (MonoMethodBuilder, 1);
315         MonoTypeBuilder *tb = object_impl_pointer (typeb);
316
317         mb->name = mono_string_to_utf8 (name);
318         mb->attrs = attrs;
319         mb->callconv = callconv;
320         mb->ret = object_impl_pointer (rettype);
321         /* ignore params ... */
322
323         if (!tb->has_default_ctor) {
324                 if (strcmp (".ctor", mb->name) == 0 && paramtypes->bounds->length == 0)
325                         tb->has_default_ctor = 1;
326         }
327         
328         tb->methods = g_list_prepend (tb->methods, mb);
329
330         return my_mono_new_object (klass, mb);
331 }
332
333 static void
334 ves_icall_set_method_body (MonoObject *methodb, MonoArrayObject *code, gint32 count)
335 {
336         MonoMethodBuilder *mb = object_impl_pointer (methodb);
337         if (code->bounds->length < count) {
338                 g_warning ("code len is less than count");
339                 return;
340         }
341         g_free (mb->code);
342         mb->code = g_malloc (count);
343         mb->code_size = count;
344         memcpy (mb->code, code->vector, count);
345 }
346
347 static MonoObject*
348 ves_icall_type_from_name (MonoObject *name)
349 {
350         return NULL;
351 }
352
353 static MonoObject*
354 ves_icall_type_from_handle (gpointer handle)
355 {
356         return my_mono_new_object (mono_defaults.type_class, handle);
357 }
358
359 static gpointer icall_map [] = {
360         /*
361          * System.Array
362          */
363         "__array_ctor",                   ves_icall_array_ctor,
364         "__array_bound_ctor",             ves_icall_array_bound_ctor,
365         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
366         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
367         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
368         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
369         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
370         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
371
372         /*
373          * System.Object
374          */
375         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
376
377         /*
378          * System.String
379          */
380         "System.String::IsInterned", mono_string_is_interned,
381         "System.String::Intern", mono_string_intern,
382
383         /*
384          * System.AppDomain
385          */
386         "System.AppDomain::getCurDomain", ves_icall_app_get_cur_domain,
387         "System.AppDomain::defineAssembly", ves_icall_app_define_assembly,
388
389         /*
390          * ModuleBuilder
391          */
392         "System.Reflection.Emit.ModuleBuilder::defineType", ves_icall_define_type,
393         
394         /*
395          * AssemblyBuilder
396          */
397         "System.Reflection.Emit.AssemblyBuilder::defineModule", ves_icall_define_module,
398         "System.Reflection.Emit.AssemblyBuilder::getDataChunk", ves_icall_get_data_chunk,
399         
400         /*
401          * TypeBuilder
402          */
403         "System.Reflection.Emit.TypeBuilder::defineMethod", ves_icall_define_method,
404         
405         /*
406          * MethodBuilder
407          */
408         "System.Reflection.Emit.MethodBuilder::set_method_body", ves_icall_set_method_body,
409         
410         /*
411          * System.Type
412          */
413         "System.Type::internal_from_name", ves_icall_type_from_name,
414         "System.Type::internal_from_handle", ves_icall_type_from_handle,
415         
416         /*
417          * System.Threading
418          */
419         "System.Threading.Thread::Thread_internal", ves_icall_System_Threading_Thread_Thread_internal,
420         "System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
421         "System.Threading.Thread::Sleep_internal", ves_icall_System_Threading_Thread_Sleep_internal,
422         "System.Threading.Thread::Schedule_internal", ves_icall_System_Threading_Thread_Schedule_internal,
423         "System.Threading.Thread::CurrentThread_internal", ves_icall_System_Threading_Thread_CurrentThread_internal,
424         "System.Threading.Thread::Join_internal", ves_icall_System_Threading_Thread_Join_internal,
425         "System.Threading.Thread::DataSlot_register", ves_icall_System_Threading_Thread_DataSlot_register,
426         "System.Threading.Thread::DataSlot_store", ves_icall_System_Threading_Thread_DataSlot_store,
427         "System.Threading.Thread::DataSlot_retrieve", ves_icall_System_Threading_Thread_DataSlot_retrieve,
428         /* Not in the System.Threading namespace, but part of the same code */
429         "System.LocalDataStoreSlot::DataSlot_unregister", ves_icall_System_LocalDataStoreSlot_DataSlot_unregister,
430         "System.Threading.Monitor::Monitor_enter", ves_icall_System_Threading_Monitor_Monitor_enter,
431         "System.Threading.Monitor::Monitor_exit", ves_icall_System_Threading_Monitor_Monitor_exit,
432         "System.Threading.Monitor::Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner,
433         "System.Threading.Monitor::Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised,
434         "System.Threading.Monitor::Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse,
435         "System.Threading.Monitor::Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all,
436         "System.Threading.Monitor::Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter,
437         "System.Threading.Monitor::Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait,
438
439         /*
440          * add other internal calls here
441          */
442         NULL, NULL
443 };
444
445 void
446 mono_init_icall ()
447 {
448         char *n;
449         int i = 0;
450
451         while ((n = icall_map [i])) {
452                 mono_add_internal_call (n, icall_map [i+1]);
453                 i += 2;
454         }
455        
456 }
457
458