1 /* src/vm/jit/argument.c - argument passing from and to JIT methods
3 Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 #include "mm/memory.h"
37 #include "native/llni.h"
40 #include "vm/global.h"
41 #include "vm/primitive.h"
42 #include "vm/resolve.h"
45 #include "vm/jit/abi-asm.h"
47 #include "vmcore/descriptor.h"
48 #include "vmcore/method.h"
51 /* argument_jitarray_load ******************************************************
53 Returns the argument specified by index from one of the passed arrays
56 *******************************************************************************/
58 imm_union argument_jitarray_load(methoddesc *md, int32_t index,
59 uint64_t *arg_regs, uint64_t *stack)
64 pd = &md->params[index];
66 switch (md->paramtypes[index].type) {
70 #if (SIZEOF_VOID_P == 8)
71 ret.l = (int64_t)stack[pd->index];
73 ret.l = *(int32_t *)(stack + pd->index);
76 #if (SIZEOF_VOID_P == 8)
77 ret.l = arg_regs[index];
79 ret.l = *(int32_t *)(arg_regs + index);
85 ret.l = (int64_t)stack[pd->index];
87 ret.l = (int64_t)arg_regs[index];
92 ret.l = (int64_t)stack[pd->index];
94 ret.l = (int64_t)arg_regs[index];
99 ret.l = (int64_t)stack[pd->index];
101 ret.l = (int64_t)arg_regs[index];
110 /* argument_jitarray_store *****************************************************
112 Stores the argument into one of the passed arrays at a slot specified
115 *******************************************************************************/
117 void argument_jitarray_store(methoddesc *md, int32_t index,
118 uint64_t *arg_regs, uint64_t *stack,
123 pd = &md->params[index];
125 switch (md->paramtypes[index].type) {
128 #if (SIZEOF_VOID_P == 8)
129 stack[pd->index] = param.l;
134 arg_regs[index] = param.l;
138 vm_abort("argument_jitarray_store: type not implemented");
144 /* argument_jitreturn_load *****************************************************
146 Loads the proper return value form the return register and returns it.
148 *******************************************************************************/
150 imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
154 switch (md->returntype.type) {
157 #if (SIZEOF_VOID_P == 8)
158 ret.l = return_regs[0];
160 ret.l = *(int32_t *)return_regs;
164 ret.l = *(int64_t *)return_regs;
167 ret.l = *(int64_t *)return_regs;
170 ret.l = *(int64_t *)return_regs;
178 /* argument_jitreturn_store ****************************************************
180 Stores the proper return value into the return registers.
182 *******************************************************************************/
184 void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
186 switch (md->returntype.type) {
188 #if (SIZEOF_VOID_P == 8)
189 return_regs[0] = ret.l;
195 vm_abort("argument_jitreturn_store: type not implemented");
201 /* argument_vmarray_store_int **************************************************
203 Helper function to store an integer into the argument array, taking
204 care of architecture specific issues.
206 *******************************************************************************/
208 static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
214 array[index] = (int64_t) value;
217 index = ARG_CNT + pd->index;
218 #if SIZEOF_VOID_P == 8
219 array[index] = (int64_t) value;
221 # if WORDS_BIGENDIAN == 1
222 array[index] = ((int64_t) value) << 32;
224 array[index] = (int64_t) value;
231 /* argument_vmarray_store_lng **************************************************
233 Helper function to store a long into the argument array, taking
234 care of architecture specific issues.
236 *******************************************************************************/
238 static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
242 #if SIZEOF_VOID_P == 8
246 index = ARG_CNT + pd->index;
248 array[index] = value;
251 /* move low and high 32-bits into it's own argument slot */
253 index = GET_LOW_REG(pd->index);
254 array[index] = value & 0x00000000ffffffff;
256 index = GET_HIGH_REG(pd->index);
257 array[index] = value >> 32;
260 index = ARG_CNT + pd->index;
261 array[index] = value;
267 /* argument_vmarray_store_flt **************************************************
269 Helper function to store a float into the argument array, taking
270 care of architecture specific issues.
272 *******************************************************************************/
274 static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
279 #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
282 index = INT_ARG_CNT + pd->index;
284 #if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
285 array[index] = value >> 32;
287 array[index] = value;
291 index = ARG_CNT + pd->index;
292 #if defined(__SPARC_64__)
293 array[index] = value >> 32;
295 array[index] = value;
301 /* argument_vmarray_store_dbl **************************************************
303 Helper function to store a double into the argument array, taking
304 care of architecture specific issues.
306 *******************************************************************************/
308 static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
313 #if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
314 index = GET_LOW_REG(pd->index);
315 array[index] = value & 0x00000000ffffffff;
317 index = GET_HIGH_REG(pd->index);
318 array[index] = value >> 32;
320 index = INT_ARG_CNT + pd->index;
321 array[index] = value;
325 index = ARG_CNT + pd->index;
326 array[index] = value;
331 /* argument_vmarray_store_adr **************************************************
333 Helper function to store an address into the argument array, taking
334 care of architecture specific issues.
336 ATTENTION: This function has to be used outside the nativeworld.
338 *******************************************************************************/
340 static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
345 /* Take the reference value out of the handle. */
347 value = LLNI_UNWRAP(h);
350 #if defined(HAS_ADDRESS_REGISTER_FILE)
351 /* When the architecture has address registers, place them
352 after integer and float registers. */
354 index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
358 array[index] = (uint64_t) (intptr_t) value;
361 index = ARG_CNT + pd->index;
362 #if SIZEOF_VOID_P == 8
363 array[index] = (uint64_t) (intptr_t) value;
365 # if WORDS_BIGENDIAN == 1
366 array[index] = ((uint64_t) (intptr_t) value) << 32;
368 array[index] = (uint64_t) (intptr_t) value;
375 /* argument_vmarray_from_valist ************************************************
377 Creates an argument array which can be passed to asm_vm_call_method.
378 The array is created from the passed valist.
380 ATTENTION: This function has to be used outside the native world.
382 *******************************************************************************/
384 uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
393 /* get the descriptors */
399 /* allocate argument array */
401 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
403 /* if method is non-static fill first block and skip `this' pointer */
408 /* the `this' pointer */
409 argument_vmarray_store_adr(array, pd, o);
416 for (; i < md->paramcount; i++, pd++, td++) {
419 value.i = va_arg(ap, int32_t);
420 argument_vmarray_store_int(array, pd, value.i);
424 value.l = va_arg(ap, int64_t);
425 argument_vmarray_store_lng(array, pd, value.l);
429 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
430 /* This is required to load the correct float value in
433 value.d = (double) va_arg(ap, double);
435 value.f = (float) va_arg(ap, double);
437 argument_vmarray_store_flt(array, pd, value.l);
441 value.d = va_arg(ap, double);
442 argument_vmarray_store_dbl(array, pd, value.l);
446 value.a = va_arg(ap, void*);
447 argument_vmarray_store_adr(array, pd, value.a);
456 /* argument_vmarray_from_jvalue ************************************************
458 Creates an argument array which can be passed to asm_vm_call_method.
459 The array is created from the passed jvalue array.
461 ATTENTION: This function has to be used outside the native world.
463 *******************************************************************************/
465 uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
475 /* get the descriptors */
481 /* allocate argument array */
483 #if defined(HAS_ADDRESS_REGISTER_FILE)
484 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse);
486 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
489 /* if method is non-static fill first block and skip `this' pointer */
494 /* the `this' pointer */
495 argument_vmarray_store_adr(array, pd, o);
502 for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
503 switch (td->decltype) {
505 argument_vmarray_store_int(array, pd, args[j].i);
509 argument_vmarray_store_lng(array, pd, args[j].j);
513 argument_vmarray_store_flt(array, pd, args[j].j);
517 argument_vmarray_store_dbl(array, pd, args[j].j);
521 argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
530 /* argument_vmarray_from_objectarray *******************************************
532 Creates an argument array which can be passed to asm_vm_call_method.
533 The array is created from the passed objectarray of boxed values.
535 ATTENTION: This function has to be used outside the native world.
538 NULL.........indicates an error while creating the array
539 (-1).........no error, but an empty array
540 otherwise....array containing the argument values
542 *******************************************************************************/
544 uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
545 java_handle_objectarray_t *params)
551 java_handle_t *param;
558 /* get the descriptors */
564 /* allocate argument array */
566 array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
568 /* The array can be NULL if we don't have any arguments to pass
569 and the architecture does not have any argument registers
570 (e.g. i386). In that case we return (-1) to indicate
571 that no exception should be thrown */
574 array = (uint64_t *)(-1);
576 /* if method is non-static fill first block and skip `this' pointer */
582 argument_vmarray_store_adr(array, pd, o);
589 for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
590 /* XXX This function can throw an exception, which should not happend
591 here, since we are outside the nativeworld. */
592 param = array_objectarray_element_get(params, j);
599 /* convert the value according to its declared type */
601 LLNI_class_get(param, c);
602 type = primitive_type_get_by_wrapperclass(c);
604 switch (td->decltype) {
605 case PRIMITIVETYPE_BOOLEAN:
607 case PRIMITIVETYPE_BOOLEAN:
608 /* This type is OK. */
615 case PRIMITIVETYPE_BYTE:
617 case PRIMITIVETYPE_BYTE:
618 /* This type is OK. */
625 case PRIMITIVETYPE_CHAR:
627 case PRIMITIVETYPE_CHAR:
628 /* This type is OK. */
635 case PRIMITIVETYPE_SHORT:
637 case PRIMITIVETYPE_BYTE:
638 case PRIMITIVETYPE_SHORT:
639 /* These types are OK. */
646 case PRIMITIVETYPE_INT:
648 case PRIMITIVETYPE_BYTE:
649 case PRIMITIVETYPE_SHORT:
650 case PRIMITIVETYPE_INT:
651 /* These types are OK. */
659 vm_abort("argument_vmarray_from_objectarray: invalid type %d",
663 value = primitive_unbox(param);
664 argument_vmarray_store_int(array, pd, value.i);
671 LLNI_class_get(param, c);
672 type = primitive_type_get_by_wrapperclass(c);
674 assert(td->decltype == PRIMITIVETYPE_LONG);
677 case PRIMITIVETYPE_BYTE:
678 case PRIMITIVETYPE_SHORT:
679 case PRIMITIVETYPE_INT:
680 case PRIMITIVETYPE_LONG:
681 /* These types are OK. */
687 value = primitive_unbox(param);
688 argument_vmarray_store_lng(array, pd, value.l);
695 LLNI_class_get(param, c);
696 type = primitive_type_get_by_wrapperclass(c);
698 assert(td->decltype == PRIMITIVETYPE_FLOAT);
701 case PRIMITIVETYPE_FLOAT:
702 /* This type is OK. */
708 value = primitive_unbox(param);
709 argument_vmarray_store_flt(array, pd, value.l);
716 LLNI_class_get(param, c);
717 type = primitive_type_get_by_wrapperclass(c);
719 assert(td->decltype == PRIMITIVETYPE_DOUBLE);
722 case PRIMITIVETYPE_FLOAT:
723 case PRIMITIVETYPE_DOUBLE:
724 /* These types are OK. */
730 value = primitive_unbox(param);
731 argument_vmarray_store_dbl(array, pd, value.l);
735 if (!resolve_class_from_typedesc(td, true, true, &c))
739 if (td->arraydim > 0) {
740 if (!builtin_arrayinstanceof(param, c))
744 if (!builtin_instanceof(param, c))
749 argument_vmarray_store_adr(array, pd, param);
753 vm_abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
762 * These are local overrides for various environment variables in Emacs.
763 * Please do not remove this and leave it at the end of the file, where
764 * Emacs will automagically detect them.
765 * ---------------------------------------------------------------------
768 * indent-tabs-mode: t
772 * vim:noexpandtab:sw=4:ts=4: