2001-09-23 Dick Porter <dick@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
14 #include <mono/metadata/object.h>
15 #include <mono/metadata/threads.h>
16
17 static MonoObject *
18 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
19 {
20         MonoArrayObject *ao, *io;
21         MonoArrayClass *ac, *ic;
22         gint32 i, pos, *ind, esize;
23         gpointer *ea;
24
25         io = (MonoArrayObject *)idxs;
26         ic = (MonoArrayClass *)io->obj.klass;
27         
28         ao = (MonoArrayObject *)this;
29         ac = (MonoArrayClass *)ao->obj.klass;
30
31         g_assert (ic->rank == 1);
32         g_assert (io->bounds [0].length == ac->rank);
33
34         ind = (guint32 *)io->vector;
35
36         pos = ind [0] - ao->bounds [0].lower_bound;
37         for (i = 1; i < ac->rank; i++)
38                 pos = pos*ao->bounds [i].length + ind [i] - 
39                         ao->bounds [i].lower_bound;
40
41         esize = mono_array_element_size (ac);
42         ea = ao->vector + (pos * esize);
43
44         if (ac->element_class->valuetype)
45                 return mono_value_box (ac->element_class, ea);
46         else
47                 return *ea;
48 }
49
50 static void 
51 ves_icall_System_Array_SetValue (MonoObject *this, MonoObject *value,
52                                  MonoObject *idxs)
53 {
54         MonoArrayObject *ao, *io, *vo;
55         MonoArrayClass *ac, *ic, *vc;
56         gint32 i, pos, *ind, esize;
57         gpointer *ea;
58
59         vo = (MonoArrayObject *)value;
60         vc = (MonoArrayClass *)vo->obj.klass;
61
62         io = (MonoArrayObject *)idxs;
63         ic = (MonoArrayClass *)io->obj.klass;
64         
65         ao = (MonoArrayObject *)this;
66         ac = (MonoArrayClass *)ao->obj.klass;
67
68         g_assert (ic->rank == 1);
69         g_assert (io->bounds [0].length == ac->rank);
70         g_assert (ac->element_class == vo->obj.klass);
71
72         ind = (guint32 *)io->vector;
73
74         pos = ind [0] - ao->bounds [0].lower_bound;
75         for (i = 1; i < ac->rank; i++)
76                 pos = pos*ao->bounds [i].length + ind [i] - 
77                         ao->bounds [i].lower_bound;
78
79         esize = mono_array_element_size (ac);
80         ea = ao->vector + (pos * esize);
81
82         if (ac->element_class->valuetype) {
83                 g_assert (vc->klass.valuetype);
84
85                 memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
86         } else
87                 *ea = (gpointer)vo;
88
89 }
90
91 static void 
92 ves_icall_array_ctor (MonoObject *this, gint32 n1, ...)
93 {
94         va_list ap;
95         MonoArrayObject *ao;
96         MonoArrayClass *ac;
97         gint32 i, s, len, esize;
98
99         va_start (ap, n1);
100
101         ao = (MonoArrayObject *)this;
102         ac = (MonoArrayClass *)this->klass;
103
104         g_assert (ac->rank >= 1);
105
106         ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
107
108         len = n1;
109         ao->bounds [0].length = n1;
110         for (i = 1; i < ac->rank; i++) {
111                 s = va_arg (ap, gint32);
112                 len *= s;
113                 ao->bounds [i].length = s;
114         }
115
116         esize = mono_array_element_size (ac);
117         ao->vector = g_malloc0 (len * esize);
118 }
119
120 static void 
121 ves_icall_array_bound_ctor (MonoObject *this, gint32 n1, ...)
122 {
123         va_list ap;
124         MonoArrayObject *ao;
125         MonoArrayClass *ac;
126         gint32 i, s, len, esize;
127
128         va_start (ap, n1);
129
130         ao = (MonoArrayObject *)this;
131         ac = (MonoArrayClass *)this->klass;
132
133         g_assert (ac->rank >= 1);
134
135         ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
136
137         ao->bounds [0].lower_bound = n1;
138         for (i = 1; i < ac->rank; i++)
139                 ao->bounds [i].lower_bound = va_arg (ap, gint32);
140
141         len = va_arg (ap, gint32);
142         ao->bounds [0].length = len;
143         for (i = 1; i < ac->rank; i++) {
144                 s = va_arg (ap, gint32);
145                 len *= s;
146                 ao->bounds [i].length = s;
147         }
148
149         esize = mono_array_element_size (ac);
150         ao->vector = g_malloc0 (len * esize);
151 }
152
153 static void
154 ves_icall_System_Array_CreateInstance ()
155 {
156         g_warning ("not implemented");
157         g_assert_not_reached ();
158 }
159
160
161 static gint32 
162 ves_icall_System_Array_GetRank (MonoObject *this)
163 {
164         return ((MonoArrayClass *)this->klass)->rank;
165 }
166
167 static gint32
168 ves_icall_System_Array_GetLength (MonoObject *this, gint32 dimension)
169 {
170         return ((MonoArrayObject *)this)->bounds [dimension].length;
171 }
172
173 static gint32
174 ves_icall_System_Array_GetLowerBound (MonoObject *this, gint32 dimension)
175 {
176         return ((MonoArrayObject *)this)->bounds [dimension].lower_bound;
177 }
178
179 static MonoObject *
180 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
181 {
182         return mono_object_clone (this);
183 }
184
185 static gpointer icall_map [] = {
186         /*
187          * System.Array
188          */
189         "__array_ctor",                   ves_icall_array_ctor,
190         "__array_bound_ctor",             ves_icall_array_bound_ctor,
191         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
192         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
193         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
194         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
195         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
196         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
197
198         /*
199          * System.Object
200          */
201         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
202
203         /*
204          * System.Threading
205          */
206         "System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
207         "System.Threading.Thread::Sleep_internal", ves_icall_System_Threading_Thread_Sleep_internal,
208         "System.Threading.Thread::Schedule_internal", ves_icall_System_Threading_Thread_Schedule_internal,
209         "System.Threading.Thread::CurrentThread_internal", ves_icall_System_Threading_Thread_CurrentThread_internal,
210
211         /*
212          * add other internal calls here
213          */
214         NULL, NULL
215 };
216
217 void
218 mono_init_icall ()
219 {
220         char *n;
221         int i = 0;
222
223         while ((n = icall_map [i])) {
224                 mono_add_internal_call (n, icall_map [i+1]);
225                 i += 2;
226         }
227        
228 }
229
230