1 /* src/vm/jit/argument.c - argument passing from and to JIT methods
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
33 #include "mm/memory.h"
35 #include "native/llni.h"
38 #include "vm/global.h"
39 #include "vm/primitive.hpp"
40 #include "vm/resolve.h"
43 #include "vm/jit/abi-asm.h"
45 #include "vmcore/descriptor.h"
46 #include "vmcore/method.h"
49 /* argument_jitarray_load ******************************************************
51 Returns the argument specified by index from one of the passed arrays
54 *******************************************************************************/
56 imm_union argument_jitarray_load(methoddesc *md, int32_t index,
57 uint64_t *arg_regs, uint64_t *stack)
62 pd = &md->params[index];
64 switch (md->paramtypes[index].type) {
68 #if (SIZEOF_VOID_P == 8)
69 ret.l = (int64_t)stack[pd->index];
71 ret.l = *(int32_t *)(stack + pd->index);
74 #if (SIZEOF_VOID_P == 8)
75 ret.l = arg_regs[index];
77 ret.l = *(int32_t *)(arg_regs + index);
83 ret.l = (int64_t)stack[pd->index];
85 ret.l = (int64_t)arg_regs[index];
90 ret.l = (int64_t)stack[pd->index];
92 ret.l = (int64_t)arg_regs[index];
97 ret.l = (int64_t)stack[pd->index];
99 ret.l = (int64_t)arg_regs[index];
108 /* argument_jitarray_store *****************************************************
110 Stores the argument into one of the passed arrays at a slot specified
113 *******************************************************************************/
115 void argument_jitarray_store(methoddesc *md, int32_t index,
116 uint64_t *arg_regs, uint64_t *stack,
121 pd = &md->params[index];
123 switch (md->paramtypes[index].type) {
126 #if (SIZEOF_VOID_P == 8)
127 stack[pd->index] = param.l;
132 arg_regs[index] = param.l;
136 vm_abort("argument_jitarray_store: type not implemented");
142 /* argument_jitreturn_load *****************************************************
144 Loads the proper return value form the return register and returns it.
146 *******************************************************************************/
148 imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
152 switch (md->returntype.type) {
155 #if (SIZEOF_VOID_P == 8)
156 ret.l = return_regs[0];
158 ret.l = *(int32_t *)return_regs;
162 ret.l = *(int64_t *)return_regs;
165 ret.l = *(int64_t *)return_regs;
168 ret.l = *(int64_t *)return_regs;
176 /* argument_jitreturn_store ****************************************************
178 Stores the proper return value into the return registers.
180 *******************************************************************************/
182 void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
184 switch (md->returntype.type) {
186 #if (SIZEOF_VOID_P == 8)
187 return_regs[0] = ret.l;
193 vm_abort("argument_jitreturn_store: type not implemented");
199 /* argument_vmarray_store_int **************************************************
201 Helper function to store an integer into the argument array, taking
202 care of architecture specific issues.
204 *******************************************************************************/
206 static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
212 array[index] = (int64_t) value;
215 index = ARG_CNT + pd->index;
216 #if SIZEOF_VOID_P == 8
217 array[index] = (int64_t) value;
219 # if WORDS_BIGENDIAN == 1
220 array[index] = ((int64_t) value) << 32;
222 array[index] = (int64_t) value;
229 /* argument_vmarray_store_lng **************************************************
231 Helper function to store a long into the argument array, taking
232 care of architecture specific issues.
234 *******************************************************************************/
236 static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
240 #if SIZEOF_VOID_P == 8
244 index = ARG_CNT + pd->index;
246 array[index] = value;
249 /* move low and high 32-bits into it's own argument slot */
251 index = GET_LOW_REG(pd->index);
252 array[index] = value & 0x00000000ffffffff;
254 index = GET_HIGH_REG(pd->index);
255 array[index] = value >> 32;
258 index = ARG_CNT + pd->index;
259 array[index] = value;
265 /* argument_vmarray_store_flt **************************************************
267 Helper function to store a float into the argument array, taking
268 care of architecture specific issues.
270 *******************************************************************************/
272 static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
277 #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
280 index = INT_ARG_CNT + pd->index;
282 #if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
283 array[index] = value >> 32;
285 array[index] = value;
289 index = ARG_CNT + pd->index;
290 #if defined(__SPARC_64__)
291 array[index] = value >> 32;
293 array[index] = value;
299 /* argument_vmarray_store_dbl **************************************************
301 Helper function to store a double into the argument array, taking
302 care of architecture specific issues.
304 *******************************************************************************/
306 static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
311 #if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
312 index = GET_LOW_REG(pd->index);
313 array[index] = value & 0x00000000ffffffff;
315 index = GET_HIGH_REG(pd->index);
316 array[index] = value >> 32;
318 index = INT_ARG_CNT + pd->index;
319 array[index] = value;
323 index = ARG_CNT + pd->index;
324 array[index] = value;
329 /* argument_vmarray_store_adr **************************************************
331 Helper function to store an address into the argument array, taking
332 care of architecture specific issues.
334 ATTENTION: This function has to be used outside the nativeworld.
336 *******************************************************************************/
338 static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
343 /* Take the reference value out of the handle. */
345 value = LLNI_UNWRAP(h);
348 #if defined(HAS_ADDRESS_REGISTER_FILE)
349 /* When the architecture has address registers, place them
350 after integer and float registers. */
352 index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
356 array[index] = (uint64_t) (intptr_t) value;
359 index = ARG_CNT + pd->index;
360 #if SIZEOF_VOID_P == 8
361 array[index] = (uint64_t) (intptr_t) value;
363 # if WORDS_BIGENDIAN == 1
364 array[index] = ((uint64_t) (intptr_t) value) << 32;
366 array[index] = (uint64_t) (intptr_t) value;
373 /* argument_vmarray_from_valist ************************************************
375 Creates an argument array which can be passed to asm_vm_call_method.
376 The array is created from the passed valist.
378 ATTENTION: This function has to be used outside the native world.
380 *******************************************************************************/
382 uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
391 /* get the descriptors */
397 /* allocate argument array */
399 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
401 /* if method is non-static fill first block and skip `this' pointer */
406 /* the `this' pointer */
407 argument_vmarray_store_adr(array, pd, o);
414 for (; i < md->paramcount; i++, pd++, td++) {
417 value.i = va_arg(ap, int32_t);
418 argument_vmarray_store_int(array, pd, value.i);
422 value.l = va_arg(ap, int64_t);
423 argument_vmarray_store_lng(array, pd, value.l);
427 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
428 /* This is required to load the correct float value in
431 value.d = (double) va_arg(ap, double);
433 value.f = (float) va_arg(ap, double);
435 argument_vmarray_store_flt(array, pd, value.l);
439 value.d = va_arg(ap, double);
440 argument_vmarray_store_dbl(array, pd, value.l);
444 value.a = va_arg(ap, void*);
445 argument_vmarray_store_adr(array, pd, value.a);
454 /* argument_vmarray_from_jvalue ************************************************
456 Creates an argument array which can be passed to asm_vm_call_method.
457 The array is created from the passed jvalue array.
459 ATTENTION: This function has to be used outside the native world.
461 *******************************************************************************/
463 uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
473 /* get the descriptors */
479 /* allocate argument array */
481 #if defined(HAS_ADDRESS_REGISTER_FILE)
482 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse);
484 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
487 /* if method is non-static fill first block and skip `this' pointer */
492 /* the `this' pointer */
493 argument_vmarray_store_adr(array, pd, o);
500 for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
501 switch (td->decltype) {
503 argument_vmarray_store_int(array, pd, args[j].i);
507 argument_vmarray_store_lng(array, pd, args[j].j);
511 argument_vmarray_store_flt(array, pd, args[j].j);
515 argument_vmarray_store_dbl(array, pd, args[j].j);
519 argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
528 /* argument_vmarray_from_objectarray *******************************************
530 Creates an argument array which can be passed to asm_vm_call_method.
531 The array is created from the passed objectarray of boxed values.
533 ATTENTION: This function has to be used outside the native world.
536 NULL.........indicates an error while creating the array
537 (-1).........no error, but an empty array
538 otherwise....array containing the argument values
540 *******************************************************************************/
542 uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
543 java_handle_objectarray_t *params)
549 java_handle_t *param;
556 /* get the descriptors */
562 /* allocate argument array */
564 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
566 /* The array can be NULL if we don't have any arguments to pass
567 and the architecture does not have any argument registers
568 (e.g. i386). In that case we return (-1) to indicate
569 that no exception should be thrown */
572 array = (uint64_t *)(-1);
574 /* if method is non-static fill first block and skip `this' pointer */
580 argument_vmarray_store_adr(array, pd, o);
587 for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
588 /* XXX This function can throw an exception, which should not happend
589 here, since we are outside the nativeworld. */
590 param = array_objectarray_element_get(params, j);
597 /* convert the value according to its declared type */
599 LLNI_class_get(param, c);
600 type = Primitive_get_type_by_wrapperclass(c);
602 switch (td->decltype) {
603 case PRIMITIVETYPE_BOOLEAN:
605 case PRIMITIVETYPE_BOOLEAN:
606 /* This type is OK. */
613 case PRIMITIVETYPE_BYTE:
615 case PRIMITIVETYPE_BYTE:
616 /* This type is OK. */
623 case PRIMITIVETYPE_CHAR:
625 case PRIMITIVETYPE_CHAR:
626 /* This type is OK. */
633 case PRIMITIVETYPE_SHORT:
635 case PRIMITIVETYPE_BYTE:
636 case PRIMITIVETYPE_SHORT:
637 /* These types are OK. */
644 case PRIMITIVETYPE_INT:
646 case PRIMITIVETYPE_BYTE:
647 case PRIMITIVETYPE_SHORT:
648 case PRIMITIVETYPE_INT:
649 /* These types are OK. */
657 vm_abort("argument_vmarray_from_objectarray: invalid type %d",
661 value = Primitive_unbox(param);
662 argument_vmarray_store_int(array, pd, value.i);
669 LLNI_class_get(param, c);
670 type = Primitive_get_type_by_wrapperclass(c);
672 assert(td->decltype == PRIMITIVETYPE_LONG);
675 case PRIMITIVETYPE_BYTE:
676 case PRIMITIVETYPE_SHORT:
677 case PRIMITIVETYPE_INT:
678 case PRIMITIVETYPE_LONG:
679 /* These types are OK. */
685 value = Primitive_unbox(param);
686 argument_vmarray_store_lng(array, pd, value.l);
693 LLNI_class_get(param, c);
694 type = Primitive_get_type_by_wrapperclass(c);
696 assert(td->decltype == PRIMITIVETYPE_FLOAT);
699 case PRIMITIVETYPE_FLOAT:
700 /* This type is OK. */
706 value = Primitive_unbox(param);
707 argument_vmarray_store_flt(array, pd, value.l);
714 LLNI_class_get(param, c);
715 type = Primitive_get_type_by_wrapperclass(c);
717 assert(td->decltype == PRIMITIVETYPE_DOUBLE);
720 case PRIMITIVETYPE_FLOAT:
721 case PRIMITIVETYPE_DOUBLE:
722 /* These types are OK. */
728 value = Primitive_unbox(param);
729 argument_vmarray_store_dbl(array, pd, value.l);
733 if (!resolve_class_from_typedesc(td, true, true, &c))
737 if (td->arraydim > 0) {
738 if (!builtin_arrayinstanceof(param, c))
742 if (!builtin_instanceof(param, c))
747 argument_vmarray_store_adr(array, pd, param);
751 vm_abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
760 * These are local overrides for various environment variables in Emacs.
761 * Please do not remove this and leave it at the end of the file, where
762 * Emacs will automagically detect them.
763 * ---------------------------------------------------------------------
766 * indent-tabs-mode: t
770 * vim:noexpandtab:sw=4:ts=4: