2001-08-28 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
13 #include <mono/metadata/loader.h>
14
15 #include "interp.h"
16
17 static void 
18 ves_icall_array_Set (MonoInvocation *frame)
19 {
20         stackval *sp = frame->stack_args;
21         MonoObject *o;
22         MonoArrayObject *ao;
23         MonoArrayClass *ac;
24         gint32 i, t, pos, esize;
25         gpointer ea;
26
27         o = frame->obj;
28         ao = (MonoArrayObject *)o;
29         ac = (MonoArrayClass *)o->klass;
30
31         g_assert (ac->rank >= 1);
32
33         pos = sp [0].data.i - ao->bounds [0].lower_bound;
34         for (i = 1; i < ac->rank; i++) {
35                 if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
36                     ao->bounds [i].length) {
37                         g_warning ("wrong array index");
38                         g_assert_not_reached ();
39                 }
40                 pos = pos*ao->bounds [i].length + sp [i].data.i - 
41                         ao->bounds [i].lower_bound;
42         }
43
44         esize = mono_array_element_size (ac);
45         ea = ao->vector + (pos * esize);
46         memcpy (ea, &sp [ac->rank].data.p, esize);
47 }
48
49 static void 
50 ves_icall_array_Get (MonoInvocation *frame)
51 {
52         stackval *sp = frame->stack_args;
53         MonoObject *o;
54         MonoArrayObject *ao;
55         MonoArrayClass *ac;
56         gint32 i, pos, esize;
57         gpointer ea;
58
59         o = frame->obj;
60         ao = (MonoArrayObject *)o;
61         ac = (MonoArrayClass *)o->klass;
62
63         g_assert (ac->rank >= 1);
64
65         pos = sp [0].data.i - ao->bounds [0].lower_bound;
66         for (i = 1; i < ac->rank; i++)
67                 pos = pos*ao->bounds [i].length + sp [i].data.i - 
68                         ao->bounds [i].lower_bound;
69
70         esize = mono_array_element_size (ac);
71         ea = ao->vector + (pos * esize);
72
73         frame->retval->type = VAL_I32; /* fixme: not really true */
74         memcpy (&frame->retval->data.p, ea, esize);
75 }
76
77 static void 
78 ves_icall_System_Array_GetValue (MonoInvocation *frame)
79 {
80         stackval *sp = frame->stack_args;
81         MonoArrayObject *ao, *io;
82         MonoArrayClass *ac, *ic;
83         gint32 i, pos, *ind, esize;
84         gpointer *ea;
85
86         g_assert (sp [0].type == VAL_OBJ); /* expect an array of integers */
87
88         io = sp [0].data.p;
89         ic = (MonoArrayClass *)io->obj.klass;
90         
91         ao = (MonoArrayObject *)frame->obj;
92         ac = (MonoArrayClass *)ao->obj.klass;
93
94         g_assert (ic->rank == 1);
95         g_assert (io->bounds [0].length == ac->rank);
96
97         ind = (guint32 *)io->vector;
98
99         pos = ind [0] - ao->bounds [0].lower_bound;
100         for (i = 1; i < ac->rank; i++)
101                 pos = pos*ao->bounds [i].length + ind [i] - 
102                         ao->bounds [i].lower_bound;
103
104         esize = mono_array_element_size (ac);
105         ea = ao->vector + (pos * esize);
106
107         frame->retval->type = VAL_OBJ; 
108
109         if (ac->element_class->valuetype)
110                 frame->retval->data.p = mono_value_box (ac->element_class, ea);
111         else
112                 frame->retval->data.p = ea;
113 }
114
115 static void 
116 ves_icall_System_Array_SetValue (MonoInvocation *frame)
117 {
118         stackval *sp = frame->stack_args;
119         MonoArrayObject *ao, *io, *vo;
120         MonoArrayClass *ac, *ic, *vc;
121         gint32 i, pos, *ind, esize;
122         gpointer *ea;
123
124         g_assert (sp [0].type == VAL_OBJ); /* the value object */
125         g_assert (sp [1].type == VAL_OBJ); /* expect an array of integers */
126
127         vo = sp [0].data.p;
128         vc = (MonoArrayClass *)vo->obj.klass;
129
130         io = sp [1].data.p;
131         ic = (MonoArrayClass *)io->obj.klass;
132         
133         ao = (MonoArrayObject *)frame->obj;
134         ac = (MonoArrayClass *)ao->obj.klass;
135
136         g_assert (ic->rank == 1);
137         g_assert (io->bounds [0].length == ac->rank);
138
139         g_assert (ac->element_class == vo->obj.klass);
140
141         ind = (guint32 *)io->vector;
142
143         pos = ind [0] - ao->bounds [0].lower_bound;
144         for (i = 1; i < ac->rank; i++)
145                 pos = pos*ao->bounds [i].length + ind [i] - 
146                         ao->bounds [i].lower_bound;
147
148         esize = mono_array_element_size (ac);
149         ea = ao->vector + (pos * esize);
150
151         if (ac->element_class->valuetype) {
152                 g_assert (vc->klass.valuetype);
153
154                 memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
155         } else
156                 ea = (gpointer)vo;
157 }
158
159 static void 
160 ves_icall_array_ctor (MonoInvocation *frame)
161 {
162         stackval *sp = frame->stack_args;
163         MonoObject *o;
164         MonoArrayObject *ao;
165         MonoArrayClass *ac;
166         gint32 i, len, esize;
167
168         o = frame->obj;
169         ao = (MonoArrayObject *)o;
170         ac = (MonoArrayClass *)o->klass;
171
172         g_assert (ac->rank >= 1);
173
174         len = sp [0].data.i;
175         for (i = 1; i < ac->rank; i++)
176                 len *= sp [i].data.i;
177
178         esize = mono_array_element_size (ac);
179         ao->vector = g_malloc0 (len * esize);
180         ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
181         
182         for (i = 0; i < ac->rank; i++)
183                 ao->bounds [i].length = sp [i].data.i;
184 }
185
186 static void 
187 ves_icall_array_bound_ctor (MonoInvocation *frame)
188 {
189         MonoObject *o;
190         MonoArrayClass *ac;
191
192         o = frame->obj;
193         ac = (MonoArrayClass *)o->klass;
194
195         g_warning ("experimental implementation");
196         g_assert_not_reached ();
197 }
198
199 static void 
200 ves_icall_System_Array_CreateInstance (MonoInvocation *frame)
201 {
202         g_warning ("not implemented");
203         g_assert_not_reached ();
204 }
205
206 static void 
207 ves_icall_System_Array_GetRank (MonoInvocation *frame)
208 {
209         MonoObject *o;
210
211         o = frame->obj;
212
213         frame->retval->data.i = ((MonoArrayClass *)o->klass)->rank;
214         frame->retval->type = VAL_I32;
215 }
216
217 static void 
218 ves_icall_System_Array_GetLength (MonoInvocation *frame)
219 {
220         stackval *sp = frame->stack_args;
221         MonoObject *o;
222
223         o = frame->obj;
224
225         frame->retval->data.i = ((MonoArrayObject *)o)->bounds [sp [0].data.i].length;
226         frame->retval->type = VAL_I32;
227 }
228
229 static void 
230 ves_icall_System_Array_GetLowerBound (MonoInvocation *frame)
231 {
232         stackval *sp = frame->stack_args;
233         MonoArrayObject *ao;
234
235         ao = (MonoArrayObject *)frame->obj;
236
237         frame->retval->data.i = ao->bounds [sp [0].data.i].lower_bound;
238         frame->retval->type = VAL_I32;
239 }
240
241 static void 
242 ves_icall_System_Object_MemberwiseClone (MonoInvocation *frame)
243 {
244         frame->retval->type = VAL_OBJ;
245         frame->retval->data.p = mono_object_clone (frame->obj);
246 }
247
248 static gpointer icall_map [] = {
249         /*
250          * System.Array
251          */
252         "__array_Set",                    ves_icall_array_Set,
253         "__array_Get",                    ves_icall_array_Get,
254         "__array_ctor",                   ves_icall_array_ctor,
255         "__array_bound_ctor",             ves_icall_array_bound_ctor,
256         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
257         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
258         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
259         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
260         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
261         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
262
263         /*
264          * System.Object
265          */
266         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
267
268         /*
269          * add other internal calls here
270          */
271         NULL, NULL
272 };
273
274 void
275 mono_init_icall ()
276 {
277         char *n;
278         int i = 0;
279
280         while ((n = icall_map [i])) {
281                 mono_add_internal_call (n, icall_map [i+1]);
282                 i += 2;
283         }
284        
285 }
286
287