1fe9e6d0b1b788118558c4f21a1f0b19dd6b50a9
[cacao.git] / src / vm / primitive.cpp
1 /* src/vm/primitive.cpp - primitive types
2
3    Copyright (C) 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30
31 #include "native/jni.h"
32 #include "native/llni.h"
33
34 #include "native/include/java_lang_Boolean.h"
35 #include "native/include/java_lang_Byte.h"
36 #include "native/include/java_lang_Short.h"
37 #include "native/include/java_lang_Character.h"
38 #include "native/include/java_lang_Integer.h"
39 #include "native/include/java_lang_Long.h"
40 #include "native/include/java_lang_Float.h"
41 #include "native/include/java_lang_Double.h"
42
43 #include "vm/builtin.h"
44 #include "vm/global.h"
45 #include "vm/primitive.hpp"
46 #include "vm/vm.hpp"
47
48 #include "vmcore/class.h"
49 #include "vmcore/globals.hpp"
50 #include "vmcore/utf8.h"
51
52
53 /**
54  * Returns the primitive class of the given class name.
55  *
56  * @param name Name of the class.
57  *
58  * @return Class structure.
59  */
60 classinfo* Primitive::get_class_by_name(utf *name)
61 {
62         int i;
63
64         /* search table of primitive classes */
65
66         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
67                 if (primitivetype_table[i].name == name)
68                         return primitivetype_table[i].class_primitive;
69
70         /* keep compiler happy */
71
72         return NULL;
73 }
74
75
76 /**
77  * Returns the primitive class of the given type.
78  *
79  * @param type Integer type of the class.
80  *
81  * @return Class structure.
82  */
83 classinfo* Primitive::get_class_by_type(int type)
84 {
85         return primitivetype_table[type].class_primitive;
86 }
87
88
89 /**
90  * Returns the primitive class of the given type.
91  *
92  * @param ch 
93  *
94  * @return Class structure.
95  */
96 classinfo* Primitive::get_class_by_char(char ch)
97 {
98         int index;
99
100         switch (ch) {
101         case 'I':
102                 index = PRIMITIVETYPE_INT;
103                 break;
104         case 'J':
105                 index = PRIMITIVETYPE_LONG;
106                 break;
107         case 'F':
108                 index = PRIMITIVETYPE_FLOAT;
109                 break;
110         case 'D':
111                 index = PRIMITIVETYPE_DOUBLE;
112                 break;
113         case 'B':
114                 index = PRIMITIVETYPE_BYTE;
115                 break;
116         case 'C':
117                 index = PRIMITIVETYPE_CHAR;
118                 break;
119         case 'S':
120                 index = PRIMITIVETYPE_SHORT;
121                 break;
122         case 'Z':
123                 index = PRIMITIVETYPE_BOOLEAN;
124                 break;
125         case 'V':
126                 index = PRIMITIVETYPE_VOID;
127                 break;
128         default:
129                 return NULL;
130         }
131
132         return primitivetype_table[index].class_primitive;
133 }
134
135
136 /**
137  * Returns the primitive array-class of the given primitive class
138  * name.
139  *
140  * @param name Name of the class.
141  *
142  * @return Class structure.
143  */
144 classinfo* Primitive::get_arrayclass_by_name(utf *name)
145 {
146         int i;
147
148         /* search table of primitive classes */
149
150         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
151                 if (primitivetype_table[i].name == name)
152                         return primitivetype_table[i].arrayclass;
153
154         /* keep compiler happy */
155
156         return NULL;
157 }
158
159
160 /**
161  * Returns the primitive array-class of the given type.
162  *
163  * @param type Integer type of the class.
164  *
165  * @return Class structure.
166  */
167 classinfo* Primitive::get_arrayclass_by_type(int type)
168 {
169         return primitivetype_table[type].arrayclass;
170 }
171
172
173 /**
174  * Returns the primitive type of the given wrapper-class.
175  *
176  * @param c Class structure.
177  *
178  * @return Integer type of the class.
179  */
180 int Primitive::get_type_by_wrapperclass(classinfo *c)
181 {
182         int i;
183
184         /* Search primitive table. */
185
186         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
187                 if (primitivetype_table[i].class_wrap == c)
188                         return i;
189
190         /* Invalid primitive wrapper-class. */
191
192         return -1;
193 }
194
195
196 /**
197  * Box a primitive of the given type.  If the type is an object,
198  * simply return it.
199  *
200  * @param type  Type of the passed value.
201  * @param value Value to box.
202  *
203  * @return Handle of the boxing Java object.
204  */
205 java_handle_t* Primitive::box(int type, imm_union value)
206 {
207         java_handle_t* o;
208
209         switch (type) {
210         case PRIMITIVETYPE_BOOLEAN:
211                 o = box((uint8_t) value.i);
212                 break;
213         case PRIMITIVETYPE_BYTE:
214                 o = box((int8_t) value.i);
215                 break;
216         case PRIMITIVETYPE_CHAR:
217                 o = box((uint16_t) value.i);
218                 break;
219         case PRIMITIVETYPE_SHORT:
220                 o = box((int16_t) value.i);
221                 break;
222         case PRIMITIVETYPE_INT:
223                 o = box(value.i);
224                 break;
225         case PRIMITIVETYPE_LONG:
226                 o = box(value.l);
227                 break;
228         case PRIMITIVETYPE_FLOAT:
229                 o = box(value.f);
230                 break;
231         case PRIMITIVETYPE_DOUBLE:
232                 o = box(value.d);
233                 break;
234         case PRIMITIVETYPE_VOID:
235                 o = (java_handle_t*) value.a;
236                 break;
237         default:
238                 o = NULL;
239                 vm_abort("primitive_box: invalid primitive type %d", type);
240         }
241
242         return o;
243 }
244
245
246 /**
247  * Unbox a primitive of the given type.  If the type is an object,
248  * simply return it.
249  *
250  * @param h Handle of the Java object.
251  *
252  * @return Unboxed value as union.
253  */
254 imm_union Primitive::unbox(java_handle_t *h)
255 {
256         classinfo *c;
257         int        type;
258         imm_union  value;
259
260         if (h == NULL) {
261                 value.a = NULL;
262                 return value;
263         }
264
265         LLNI_class_get(h, c);
266
267         type = get_type_by_wrapperclass(c);
268
269         switch (type) {
270         case PRIMITIVETYPE_BOOLEAN:
271                 value.i = unbox_boolean(h);
272                 break;
273         case PRIMITIVETYPE_BYTE:
274                 value.i = unbox_byte(h);
275                 break;
276         case PRIMITIVETYPE_CHAR:
277                 value.i = unbox_char(h);
278                 break;
279         case PRIMITIVETYPE_SHORT:
280                 value.i = unbox_short(h);
281                 break;
282         case PRIMITIVETYPE_INT:
283                 value.i = unbox_int(h);
284                 break;
285         case PRIMITIVETYPE_LONG:
286                 value.l = unbox_long(h);
287                 break;
288         case PRIMITIVETYPE_FLOAT:
289                 value.f = unbox_float(h);
290                 break;
291         case PRIMITIVETYPE_DOUBLE:
292                 value.d = unbox_double(h);
293                 break;
294         case -1:
295                 /* If type is -1 the object is not a primitive box but a
296                    normal object. */
297                 value.a = h;
298                 break;
299         default:
300                 vm_abort("Primitive::unbox: invalid primitive type %d", type);
301         }
302
303         return value;
304 }
305
306
307 /* primitive_box_xxx ***********************************************************
308
309    Box a primitive type.
310
311 *******************************************************************************/
312
313 #define PRIMITIVE_BOX_TYPE(name, object, type)  \
314 java_handle_t* Primitive::box(type value)       \
315 {                                                   \
316         java_handle_t      *o;                          \
317         java_lang_##object *jo;                         \
318                                                     \
319         o = builtin_new(class_java_lang_##object);      \
320                                                     \
321         if (o == NULL)                                  \
322                 return NULL;                                \
323                                                     \
324         jo = (java_lang_##object *) o;                  \
325                                                     \
326         LLNI_field_set_val(jo, value, value);                   \
327                                                     \
328         return o;                                       \
329 }
330
331 PRIMITIVE_BOX_TYPE(boolean, Boolean,   uint8_t)
332 PRIMITIVE_BOX_TYPE(byte,    Byte,      int8_t)
333 PRIMITIVE_BOX_TYPE(char,    Character, uint16_t)
334 PRIMITIVE_BOX_TYPE(short,   Short,     int16_t)
335 PRIMITIVE_BOX_TYPE(int,     Integer,   int32_t)
336 PRIMITIVE_BOX_TYPE(long,    Long,      int64_t)
337 PRIMITIVE_BOX_TYPE(float,   Float,     float)
338 PRIMITIVE_BOX_TYPE(double,  Double,    double)
339
340
341 /* primitive_unbox_xxx *********************************************************
342
343    Unbox a primitive type.
344
345 *******************************************************************************/
346
347 #define PRIMITIVE_UNBOX_TYPE(name, object, type)        \
348 type Primitive::unbox_##name(java_handle_t *h)  \
349 {                                                 \
350         java_lang_##object *jo;                       \
351         type                value;                    \
352                                                   \
353         jo = (java_lang_##object *) h;                \
354                                                   \
355         LLNI_field_get_val(jo, value, value);         \
356                                                   \
357         return value;                                 \
358 }
359
360 PRIMITIVE_UNBOX_TYPE(boolean, Boolean,   uint8_t)
361 PRIMITIVE_UNBOX_TYPE(byte,    Byte,      int8_t)
362 PRIMITIVE_UNBOX_TYPE(char,    Character, uint16_t)
363 PRIMITIVE_UNBOX_TYPE(short,   Short,     int16_t)
364 PRIMITIVE_UNBOX_TYPE(int,     Integer,   int32_t)
365 PRIMITIVE_UNBOX_TYPE(long,    Long,      int64_t)
366 PRIMITIVE_UNBOX_TYPE(float,   Float,     float)
367 PRIMITIVE_UNBOX_TYPE(double,  Double,    double)
368
369
370 // Legacy C interface.
371
372 extern "C" {
373
374         classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
375 classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
376 classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
377 classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
378 classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
379 int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
380 java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
381 imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(h); }
382 }
383
384
385 /*
386  * These are local overrides for various environment variables in Emacs.
387  * Please do not remove this and leave it at the end of the file, where
388  * Emacs will automagically detect them.
389  * ---------------------------------------------------------------------
390  * Local variables:
391  * mode: c++
392  * indent-tabs-mode: t
393  * c-basic-offset: 4
394  * tab-width: 4
395  * End:
396  * vim:noexpandtab:sw=4:ts=4:
397  */