Merged with tip.
[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.h"
47
48 #include "vmcore/class.h"
49 #include "vmcore/utf8.h"
50
51
52 /**
53  * Returns the primitive class of the given class name.
54  *
55  * @param name Name of the class.
56  *
57  * @return Class structure.
58  */
59 classinfo* Primitive::get_class_by_name(utf *name)
60 {
61         int i;
62
63         /* search table of primitive classes */
64
65         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
66                 if (primitivetype_table[i].name == name)
67                         return primitivetype_table[i].class_primitive;
68
69         /* keep compiler happy */
70
71         return NULL;
72 }
73
74
75 /**
76  * Returns the primitive class of the given type.
77  *
78  * @param type Integer type of the class.
79  *
80  * @return Class structure.
81  */
82 classinfo* Primitive::get_class_by_type(int type)
83 {
84         return primitivetype_table[type].class_primitive;
85 }
86
87
88 /**
89  * Returns the primitive class of the given type.
90  *
91  * @param ch 
92  *
93  * @return Class structure.
94  */
95 classinfo* Primitive::get_class_by_char(char ch)
96 {
97         int index;
98
99         switch (ch) {
100         case 'I':
101                 index = PRIMITIVETYPE_INT;
102                 break;
103         case 'J':
104                 index = PRIMITIVETYPE_LONG;
105                 break;
106         case 'F':
107                 index = PRIMITIVETYPE_FLOAT;
108                 break;
109         case 'D':
110                 index = PRIMITIVETYPE_DOUBLE;
111                 break;
112         case 'B':
113                 index = PRIMITIVETYPE_BYTE;
114                 break;
115         case 'C':
116                 index = PRIMITIVETYPE_CHAR;
117                 break;
118         case 'S':
119                 index = PRIMITIVETYPE_SHORT;
120                 break;
121         case 'Z':
122                 index = PRIMITIVETYPE_BOOLEAN;
123                 break;
124         case 'V':
125                 index = PRIMITIVETYPE_VOID;
126                 break;
127         default:
128                 return NULL;
129         }
130
131         return primitivetype_table[index].class_primitive;
132 }
133
134
135 /**
136  * Returns the primitive array-class of the given primitive class
137  * name.
138  *
139  * @param name Name of the class.
140  *
141  * @return Class structure.
142  */
143 classinfo* Primitive::get_arrayclass_by_name(utf *name)
144 {
145         int i;
146
147         /* search table of primitive classes */
148
149         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
150                 if (primitivetype_table[i].name == name)
151                         return primitivetype_table[i].arrayclass;
152
153         /* keep compiler happy */
154
155         return NULL;
156 }
157
158
159 /**
160  * Returns the primitive array-class of the given type.
161  *
162  * @param type Integer type of the class.
163  *
164  * @return Class structure.
165  */
166 classinfo* Primitive::get_arrayclass_by_type(int type)
167 {
168         return primitivetype_table[type].arrayclass;
169 }
170
171
172 /**
173  * Returns the primitive type of the given wrapper-class.
174  *
175  * @param c Class structure.
176  *
177  * @return Integer type of the class.
178  */
179 int Primitive::get_type_by_wrapperclass(classinfo *c)
180 {
181         int i;
182
183         /* Search primitive table. */
184
185         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
186                 if (primitivetype_table[i].class_wrap == c)
187                         return i;
188
189         /* Invalid primitive wrapper-class. */
190
191         return -1;
192 }
193
194
195 /**
196  * Box a primitive of the given type.  If the type is an object,
197  * simply return it.
198  *
199  * @param type  Type of the passed value.
200  * @param value Value to box.
201  *
202  * @return Handle of the boxing Java object.
203  */
204 java_handle_t* Primitive::box(int type, imm_union value)
205 {
206         java_handle_t* o;
207
208         switch (type) {
209         case PRIMITIVETYPE_BOOLEAN:
210                 o = box((uint8_t) value.i);
211                 break;
212         case PRIMITIVETYPE_BYTE:
213                 o = box((int8_t) value.i);
214                 break;
215         case PRIMITIVETYPE_CHAR:
216                 o = box((uint16_t) value.i);
217                 break;
218         case PRIMITIVETYPE_SHORT:
219                 o = box((int16_t) value.i);
220                 break;
221         case PRIMITIVETYPE_INT:
222                 o = box(value.i);
223                 break;
224         case PRIMITIVETYPE_LONG:
225                 o = box(value.l);
226                 break;
227         case PRIMITIVETYPE_FLOAT:
228                 o = box(value.f);
229                 break;
230         case PRIMITIVETYPE_DOUBLE:
231                 o = box(value.d);
232                 break;
233         case PRIMITIVETYPE_VOID:
234                 o = (java_handle_t*) value.a;
235                 break;
236         default:
237                 o = NULL;
238                 vm_abort("primitive_box: invalid primitive type %d", type);
239         }
240
241         return o;
242 }
243
244
245 /**
246  * Unbox a primitive of the given type.  If the type is an object,
247  * simply return it.
248  *
249  * @param h Handle of the Java object.
250  *
251  * @return Unboxed value as union.
252  */
253 imm_union Primitive::unbox(java_handle_t *h)
254 {
255         classinfo *c;
256         int        type;
257         imm_union  value;
258
259         if (h == NULL) {
260                 value.a = NULL;
261                 return value;
262         }
263
264         LLNI_class_get(h, c);
265
266         type = get_type_by_wrapperclass(c);
267
268         switch (type) {
269         case PRIMITIVETYPE_BOOLEAN:
270                 value.i = unbox_boolean(h);
271                 break;
272         case PRIMITIVETYPE_BYTE:
273                 value.i = unbox_byte(h);
274                 break;
275         case PRIMITIVETYPE_CHAR:
276                 value.i = unbox_char(h);
277                 break;
278         case PRIMITIVETYPE_SHORT:
279                 value.i = unbox_short(h);
280                 break;
281         case PRIMITIVETYPE_INT:
282                 value.i = unbox_int(h);
283                 break;
284         case PRIMITIVETYPE_LONG:
285                 value.l = unbox_long(h);
286                 break;
287         case PRIMITIVETYPE_FLOAT:
288                 value.f = unbox_float(h);
289                 break;
290         case PRIMITIVETYPE_DOUBLE:
291                 value.d = unbox_double(h);
292                 break;
293         case -1:
294                 /* If type is -1 the object is not a primitive box but a
295                    normal object. */
296                 value.a = h;
297                 break;
298         default:
299                 vm_abort("Primitive::unbox: invalid primitive type %d", type);
300         }
301
302         return value;
303 }
304
305
306 /* primitive_box_xxx ***********************************************************
307
308    Box a primitive type.
309
310 *******************************************************************************/
311
312 #define PRIMITIVE_BOX_TYPE(name, object, type)  \
313 java_handle_t* Primitive::box(type value)       \
314 {                                                   \
315         java_handle_t      *o;                          \
316         java_lang_##object *jo;                         \
317                                                     \
318         o = builtin_new(class_java_lang_##object);      \
319                                                     \
320         if (o == NULL)                                  \
321                 return NULL;                                \
322                                                     \
323         jo = (java_lang_##object *) o;                  \
324                                                     \
325         LLNI_field_set_val(jo, value, value);                   \
326                                                     \
327         return o;                                       \
328 }
329
330 PRIMITIVE_BOX_TYPE(boolean, Boolean,   uint8_t)
331 PRIMITIVE_BOX_TYPE(byte,    Byte,      int8_t)
332 PRIMITIVE_BOX_TYPE(char,    Character, uint16_t)
333 PRIMITIVE_BOX_TYPE(short,   Short,     int16_t)
334 PRIMITIVE_BOX_TYPE(int,     Integer,   int32_t)
335 PRIMITIVE_BOX_TYPE(long,    Long,      int64_t)
336 PRIMITIVE_BOX_TYPE(float,   Float,     float)
337 PRIMITIVE_BOX_TYPE(double,  Double,    double)
338
339
340 /* primitive_unbox_xxx *********************************************************
341
342    Unbox a primitive type.
343
344 *******************************************************************************/
345
346 #define PRIMITIVE_UNBOX_TYPE(name, object, type)        \
347 type Primitive::unbox_##name(java_handle_t *h)  \
348 {                                                 \
349         java_lang_##object *jo;                       \
350         type                value;                    \
351                                                   \
352         jo = (java_lang_##object *) h;                \
353                                                   \
354         LLNI_field_get_val(jo, value, value);         \
355                                                   \
356         return value;                                 \
357 }
358
359 PRIMITIVE_UNBOX_TYPE(boolean, Boolean,   uint8_t)
360 PRIMITIVE_UNBOX_TYPE(byte,    Byte,      int8_t)
361 PRIMITIVE_UNBOX_TYPE(char,    Character, uint16_t)
362 PRIMITIVE_UNBOX_TYPE(short,   Short,     int16_t)
363 PRIMITIVE_UNBOX_TYPE(int,     Integer,   int32_t)
364 PRIMITIVE_UNBOX_TYPE(long,    Long,      int64_t)
365 PRIMITIVE_UNBOX_TYPE(float,   Float,     float)
366 PRIMITIVE_UNBOX_TYPE(double,  Double,    double)
367
368
369 // Legacy C interface.
370
371 extern "C" {
372
373         classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
374 classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
375 classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
376 classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
377 classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
378 int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
379 java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
380 imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(h); }
381 }
382
383
384 /*
385  * These are local overrides for various environment variables in Emacs.
386  * Please do not remove this and leave it at the end of the file, where
387  * Emacs will automagically detect them.
388  * ---------------------------------------------------------------------
389  * Local variables:
390  * mode: c++
391  * indent-tabs-mode: t
392  * c-basic-offset: 4
393  * tab-width: 4
394  * End:
395  * vim:noexpandtab:sw=4:ts=4:
396  */