ae64eb8272895e923184baec8370ee610a2b2940
[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/llni.h"
32
33 #include "vm/builtin.h"
34 #include "vm/class.h"
35 #include "vm/global.h"
36 #include "vm/globals.hpp"
37 #include "vm/javaobjects.hpp"
38 #include "vm/primitive.hpp"
39 #include "vm/utf8.h"
40 #include "vm/vm.hpp"
41
42
43 /**
44  * Returns the primitive class of the given class name.
45  *
46  * @param name Name of the class.
47  *
48  * @return Class structure.
49  */
50 classinfo* Primitive::get_class_by_name(utf *name)
51 {
52         int i;
53
54         /* search table of primitive classes */
55
56         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
57                 if (primitivetype_table[i].name == name)
58                         return primitivetype_table[i].class_primitive;
59
60         /* keep compiler happy */
61
62         return NULL;
63 }
64
65
66 /**
67  * Returns the primitive class of the given type.
68  *
69  * @param type Integer type of the class.
70  *
71  * @return Class structure.
72  */
73 classinfo* Primitive::get_class_by_type(int type)
74 {
75         return primitivetype_table[type].class_primitive;
76 }
77
78
79 /**
80  * Returns the primitive class of the given type.
81  *
82  * @param ch 
83  *
84  * @return Class structure.
85  */
86 classinfo* Primitive::get_class_by_char(char ch)
87 {
88         int index;
89
90         switch (ch) {
91         case 'I':
92                 index = PRIMITIVETYPE_INT;
93                 break;
94         case 'J':
95                 index = PRIMITIVETYPE_LONG;
96                 break;
97         case 'F':
98                 index = PRIMITIVETYPE_FLOAT;
99                 break;
100         case 'D':
101                 index = PRIMITIVETYPE_DOUBLE;
102                 break;
103         case 'B':
104                 index = PRIMITIVETYPE_BYTE;
105                 break;
106         case 'C':
107                 index = PRIMITIVETYPE_CHAR;
108                 break;
109         case 'S':
110                 index = PRIMITIVETYPE_SHORT;
111                 break;
112         case 'Z':
113                 index = PRIMITIVETYPE_BOOLEAN;
114                 break;
115         case 'V':
116                 index = PRIMITIVETYPE_VOID;
117                 break;
118         default:
119                 return NULL;
120         }
121
122         return primitivetype_table[index].class_primitive;
123 }
124
125
126 /**
127  * Returns the primitive array-class of the given primitive class
128  * name.
129  *
130  * @param name Name of the class.
131  *
132  * @return Class structure.
133  */
134 classinfo* Primitive::get_arrayclass_by_name(utf *name)
135 {
136         int i;
137
138         /* search table of primitive classes */
139
140         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
141                 if (primitivetype_table[i].name == name)
142                         return primitivetype_table[i].arrayclass;
143
144         /* keep compiler happy */
145
146         return NULL;
147 }
148
149
150 /**
151  * Returns the primitive array-class of the given type.
152  *
153  * @param type Integer type of the class.
154  *
155  * @return Class structure.
156  */
157 classinfo* Primitive::get_arrayclass_by_type(int type)
158 {
159         return primitivetype_table[type].arrayclass;
160 }
161
162
163 /**
164  * Returns the primitive type of the given wrapper-class.
165  *
166  * @param c Class structure.
167  *
168  * @return Integer type of the class.
169  */
170 int Primitive::get_type_by_wrapperclass(classinfo *c)
171 {
172         int i;
173
174         /* Search primitive table. */
175
176         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
177                 if (primitivetype_table[i].class_wrap == c)
178                         return i;
179
180         /* Invalid primitive wrapper-class. */
181
182         return -1;
183 }
184
185
186 /**
187  * Box a primitive of the given type.  If the type is an object,
188  * simply return it.
189  *
190  * @param type  Type of the passed value.
191  * @param value Value to box.
192  *
193  * @return Handle of the boxing Java object.
194  */
195 java_handle_t* Primitive::box(int type, imm_union value)
196 {
197         java_handle_t* o;
198
199         switch (type) {
200         case PRIMITIVETYPE_BOOLEAN:
201                 o = box((uint8_t) value.i);
202                 break;
203         case PRIMITIVETYPE_BYTE:
204                 o = box((int8_t) value.i);
205                 break;
206         case PRIMITIVETYPE_CHAR:
207                 o = box((uint16_t) value.i);
208                 break;
209         case PRIMITIVETYPE_SHORT:
210                 o = box((int16_t) value.i);
211                 break;
212         case PRIMITIVETYPE_INT:
213                 o = box(value.i);
214                 break;
215         case PRIMITIVETYPE_LONG:
216                 o = box(value.l);
217                 break;
218         case PRIMITIVETYPE_FLOAT:
219                 o = box(value.f);
220                 break;
221         case PRIMITIVETYPE_DOUBLE:
222                 o = box(value.d);
223                 break;
224         case PRIMITIVETYPE_VOID:
225                 o = (java_handle_t*) value.a;
226                 break;
227         default:
228                 o = NULL;
229                 VM::get_current()->abort("primitive_box: invalid primitive type %d", type);
230         }
231
232         return o;
233 }
234
235
236 /**
237  * Unbox a primitive of the given type.  If the type is an object,
238  * simply return it.
239  *
240  * @param h Handle of the Java object.
241  *
242  * @return Unboxed value as union.
243  */
244 imm_union Primitive::unbox(java_handle_t *h)
245 {
246         classinfo *c;
247         int        type;
248         imm_union  value;
249
250         if (h == NULL) {
251                 value.a = NULL;
252                 return value;
253         }
254
255         LLNI_class_get(h, c);
256
257         type = get_type_by_wrapperclass(c);
258
259         switch (type) {
260         case PRIMITIVETYPE_BOOLEAN:
261                 value.i = unbox_boolean(h);
262                 break;
263         case PRIMITIVETYPE_BYTE:
264                 value.i = unbox_byte(h);
265                 break;
266         case PRIMITIVETYPE_CHAR:
267                 value.i = unbox_char(h);
268                 break;
269         case PRIMITIVETYPE_SHORT:
270                 value.i = unbox_short(h);
271                 break;
272         case PRIMITIVETYPE_INT:
273                 value.i = unbox_int(h);
274                 break;
275         case PRIMITIVETYPE_LONG:
276                 value.l = unbox_long(h);
277                 break;
278         case PRIMITIVETYPE_FLOAT:
279                 value.f = unbox_float(h);
280                 break;
281         case PRIMITIVETYPE_DOUBLE:
282                 value.d = unbox_double(h);
283                 break;
284         case -1:
285                 /* If type is -1 the object is not a primitive box but a
286                    normal object. */
287                 value.a = h;
288                 break;
289         default:
290                 VM::get_current()->abort("Primitive::unbox: invalid primitive type %d", type);
291         }
292
293         return value;
294 }
295
296
297 /**
298  * Box a primitive type.
299  */
300 java_handle_t* Primitive::box(uint8_t value)
301 {
302         java_handle_t *h = builtin_new(class_java_lang_Boolean);
303
304         if (h == NULL)
305                 return NULL;
306
307         java_lang_Boolean b(h);
308         b.set_value(value);
309
310         return h;
311 }
312
313 java_handle_t* Primitive::box(int8_t value)
314 {
315         java_handle_t *h = builtin_new(class_java_lang_Byte);
316
317         if (h == NULL)
318                 return NULL;
319
320         java_lang_Byte b(h);
321         b.set_value(value);
322
323         return h;
324 }
325
326 java_handle_t* Primitive::box(uint16_t value)
327 {
328         java_handle_t *h = builtin_new(class_java_lang_Character);
329
330         if (h == NULL)
331                 return NULL;
332
333         java_lang_Character c(h);
334         c.set_value(value);
335
336         return h;
337 }
338
339 java_handle_t* Primitive::box(int16_t value)
340 {
341         java_handle_t *h = builtin_new(class_java_lang_Short);
342
343         if (h == NULL)
344                 return NULL;
345
346         java_lang_Short s(h);
347         s.set_value(value);
348
349         return h;
350 }
351
352 java_handle_t* Primitive::box(int32_t value)
353 {
354         java_handle_t *h = builtin_new(class_java_lang_Integer);
355
356         if (h == NULL)
357                 return NULL;
358
359         java_lang_Integer i(h);
360         i.set_value(value);
361
362         return h;
363 }
364
365 java_handle_t* Primitive::box(int64_t value)
366 {
367         java_handle_t *h = builtin_new(class_java_lang_Long);
368
369         if (h == NULL)
370                 return NULL;
371
372         java_lang_Long l(h);
373         l.set_value(value);
374
375         return h;
376 }
377
378 java_handle_t* Primitive::box(float value)
379 {
380         java_handle_t *h = builtin_new(class_java_lang_Float);
381
382         if (h == NULL)
383                 return NULL;
384
385         java_lang_Float f(h);
386         f.set_value(value);
387
388         return h;
389 }
390
391 java_handle_t* Primitive::box(double value)
392 {
393         java_handle_t *h = builtin_new(class_java_lang_Double);
394
395         if (h == NULL)
396                 return NULL;
397
398         java_lang_Double d(h);
399         d.set_value(value);
400
401         return h;
402 }
403
404
405
406 /**
407  * Unbox a primitive type.
408  */
409
410 // template<class T> T Primitive::unbox(java_handle_t *h)
411 // {
412 //      return java_lang_Boolean::get_value(h);
413 // }
414
415 inline uint8_t Primitive::unbox_boolean(java_handle_t *h)
416 {
417         java_lang_Boolean b(h);
418         return b.get_value();
419 }
420
421 inline int8_t Primitive::unbox_byte(java_handle_t *h)
422 {
423         java_lang_Byte b(h);
424         return b.get_value();
425 }
426
427 inline uint16_t Primitive::unbox_char(java_handle_t *h)
428 {
429         java_lang_Character c(h);
430         return c.get_value();
431 }
432
433 inline int16_t Primitive::unbox_short(java_handle_t *h)
434 {
435         java_lang_Short s(h);
436         return s.get_value();
437 }
438
439 inline int32_t Primitive::unbox_int(java_handle_t *h)
440 {
441         java_lang_Integer i(h);
442         return i.get_value();
443 }
444
445 inline int64_t Primitive::unbox_long(java_handle_t *h)
446 {
447         java_lang_Long l(h);
448         return l.get_value();
449 }
450
451 inline float Primitive::unbox_float(java_handle_t *h)
452 {
453         java_lang_Float f(h);
454         return f.get_value();
455 }
456
457 inline double Primitive::unbox_double(java_handle_t *h)
458 {
459         java_lang_Double d(h);
460         return d.get_value();
461 }
462
463
464
465 // Legacy C interface.
466
467 extern "C" {
468
469         classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
470 classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
471 classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
472 classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
473 classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
474 int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
475 java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
476 imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(h); }
477 }
478
479
480 /*
481  * These are local overrides for various environment variables in Emacs.
482  * Please do not remove this and leave it at the end of the file, where
483  * Emacs will automagically detect them.
484  * ---------------------------------------------------------------------
485  * Local variables:
486  * mode: c++
487  * indent-tabs-mode: t
488  * c-basic-offset: 4
489  * tab-width: 4
490  * End:
491  * vim:noexpandtab:sw=4:ts=4:
492  */