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