* src/vm/jit/x86_64/asmpart.S (asm_abstractmethoderror): Keep stack aligned.
[cacao.git] / src / vm / jit / argument.cpp
1 /* src/vm/jit/argument.cpp - argument passing from and to JIT methods
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 "arch.h"
32
33 #include "mm/memory.hpp"
34
35 #include "native/llni.h"
36
37 #include "vm/array.hpp"
38 #include "vm/descriptor.hpp"
39 #include "vm/global.h"
40 #include "vm/method.hpp"
41 #include "vm/primitive.hpp"
42 #include "vm/resolve.hpp"
43 #include "vm/vm.hpp"
44
45 #include "vm/jit/abi-asm.h"
46
47
48 /* argument_jitarray_load ******************************************************
49  
50    Returns the argument specified by index from one of the passed arrays
51    and returns it.
52
53 *******************************************************************************/
54
55 imm_union argument_jitarray_load(methoddesc *md, int32_t index,
56                                                                  uint64_t *arg_regs, uint64_t *stack)
57 {
58         imm_union  ret;
59         paramdesc *pd;
60
61         pd = &md->params[index];
62
63         switch (md->paramtypes[index].type) {
64                 case TYPE_INT:
65                 case TYPE_ADR:
66                         if (pd->inmemory) {
67 #if (SIZEOF_VOID_P == 8)
68                                 ret.l = (int64_t)stack[pd->index];
69 #else
70                                 ret.l = *(int32_t *)(stack + pd->index);
71 #endif
72                         } else {
73 #if (SIZEOF_VOID_P == 8)
74                                 ret.l = arg_regs[index];
75 #else
76                                 ret.l = *(int32_t *)(arg_regs + index);
77 #endif
78                         }
79                         break;
80                 case TYPE_LNG:
81                         if (pd->inmemory) {
82                                 ret.l = (int64_t)stack[pd->index];
83                         } else {
84                                 ret.l = (int64_t)arg_regs[index];
85                         }
86                         break;
87                 case TYPE_FLT:
88                         if (pd->inmemory) {
89                                 ret.l = (int64_t)stack[pd->index];
90                         } else {
91                                 ret.l = (int64_t)arg_regs[index];
92                         }
93                         break;
94                 case TYPE_DBL:
95                         if (pd->inmemory) {
96                                 ret.l = (int64_t)stack[pd->index];
97                         } else {
98                                 ret.l = (int64_t)arg_regs[index];
99                         }
100                         break;
101         }
102
103         return ret;
104 }
105
106
107 /* argument_jitarray_store *****************************************************
108  
109    Stores the argument into one of the passed arrays at a slot specified
110    by index.
111
112 *******************************************************************************/
113
114 void argument_jitarray_store(methoddesc *md, int32_t index,
115                                                          uint64_t *arg_regs, uint64_t *stack,
116                                                          imm_union param)
117 {
118         paramdesc *pd;
119
120         pd = &md->params[index];
121
122         switch (md->paramtypes[index].type) {
123                 case TYPE_ADR:
124                         if (pd->inmemory) {
125 #if (SIZEOF_VOID_P == 8)
126                                 stack[pd->index] = param.l;
127 #else
128                                 assert(0);
129 #endif
130                         } else {
131                                 arg_regs[index] = param.l;
132                         }
133                         break;
134                 default:
135                         os::abort("argument_jitarray_store: type not implemented");
136                         break;
137         }
138 }
139
140
141 /* argument_jitreturn_load *****************************************************
142
143    Loads the proper return value form the return register and returns it.
144
145 *******************************************************************************/
146
147 imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
148 {
149         imm_union ret;
150
151         switch (md->returntype.type) {
152                 case TYPE_INT:
153                 case TYPE_ADR:
154 #if (SIZEOF_VOID_P == 8)
155                         ret.l = return_regs[0];
156 #else
157                         ret.l = *(int32_t *)return_regs;
158 #endif
159                         break;
160                 case TYPE_LNG:
161                         ret.l = *(int64_t *)return_regs;
162                         break;
163                 case TYPE_FLT:
164                         ret.l = *(int64_t *)return_regs;
165                         break;
166                 case TYPE_DBL:
167                         ret.l = *(int64_t *)return_regs;
168                         break;
169         }
170
171         return ret;
172 }
173
174
175 /* argument_jitreturn_store ****************************************************
176
177    Stores the proper return value into the return registers.
178
179 *******************************************************************************/
180
181 void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
182 {
183         switch (md->returntype.type) {
184                 case TYPE_ADR:
185 #if (SIZEOF_VOID_P == 8)
186                         return_regs[0] = ret.l;
187 #else
188                         assert(0);
189 #endif
190                         break;
191                 default:
192                         os::abort("argument_jitreturn_store: type not implemented");
193                         break;
194         }
195 }
196
197
198 /* argument_vmarray_store_int **************************************************
199
200    Helper function to store an integer into the argument array, taking
201    care of architecture specific issues.
202
203 *******************************************************************************/
204
205 static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
206 {
207         int32_t index;
208
209         if (!pd->inmemory) {
210                 index        = pd->index;
211                 array[index] = (int64_t) value;
212         }
213         else {
214                 index        = ARG_CNT + pd->index;
215 #if SIZEOF_VOID_P == 8
216                 array[index] = (int64_t) value;
217 #else
218 # if WORDS_BIGENDIAN == 1
219                 array[index] = ((int64_t) value) << 32;
220 # else
221                 array[index] = (int64_t) value;
222 # endif
223 #endif
224         }
225 }
226
227
228 /* argument_vmarray_store_lng **************************************************
229
230    Helper function to store a long into the argument array, taking
231    care of architecture specific issues.
232
233 *******************************************************************************/
234
235 static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
236 {
237         int32_t index;
238
239 #if SIZEOF_VOID_P == 8
240         if (!pd->inmemory)
241                 index = pd->index;
242         else
243                 index = ARG_CNT + pd->index;
244
245         array[index] = value;
246 #else
247         if (!pd->inmemory) {
248                 /* move low and high 32-bits into it's own argument slot */
249
250                 index        = GET_LOW_REG(pd->index);
251                 array[index] = value & 0x00000000ffffffff;
252
253                 index        = GET_HIGH_REG(pd->index);
254                 array[index] = value >> 32;
255         }
256         else {
257                 index        = ARG_CNT + pd->index;
258                 array[index] = value;
259         }
260 #endif
261 }
262
263
264 /* argument_vmarray_store_flt **************************************************
265
266    Helper function to store a float into the argument array, taking
267    care of architecture specific issues.
268
269 *******************************************************************************/
270
271 static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
272 {
273         int32_t index;
274
275         if (!pd->inmemory) {
276 #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
277                 index        = pd->index;
278 #else
279                 index        = INT_ARG_CNT + pd->index;
280 #endif
281 #if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
282                 array[index] = value >> 32;
283 #else
284                 array[index] = value;
285 #endif
286         }
287         else {
288                 index        = ARG_CNT + pd->index;
289 #if defined(__SPARC_64__)
290                 array[index] = value >> 32;
291 #else
292                 array[index] = value;
293 #endif
294         }
295 }
296
297
298 /* argument_vmarray_store_dbl **************************************************
299
300    Helper function to store a double into the argument array, taking
301    care of architecture specific issues.
302
303 *******************************************************************************/
304
305 static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
306 {
307         int32_t index;
308
309         if (!pd->inmemory) {
310 #if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
311                 index        = GET_LOW_REG(pd->index);
312                 array[index] = value & 0x00000000ffffffff;
313
314                 index        = GET_HIGH_REG(pd->index);
315                 array[index] = value >> 32;
316 #else
317                 index        = INT_ARG_CNT + pd->index;
318                 array[index] = value;
319 #endif
320         }
321         else {
322                 index        = ARG_CNT + pd->index;
323                 array[index] = value;
324         }
325 }
326
327
328 /* argument_vmarray_store_adr **************************************************
329
330    Helper function to store an address into the argument array, taking
331    care of architecture specific issues.
332
333    ATTENTION: This function has to be used outside the nativeworld.
334
335 *******************************************************************************/
336
337 static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
338 {
339         void    *value;
340         int32_t  index;
341
342         /* Take the reference value out of the handle. */
343
344         value = LLNI_UNWRAP(h);
345
346         if (!pd->inmemory) {
347 #if defined(HAS_ADDRESS_REGISTER_FILE)
348                 /* When the architecture has address registers, place them
349                    after integer and float registers. */
350
351                 index        = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
352 #else
353                 index        = pd->index;
354 #endif
355                 array[index] = (uint64_t) (intptr_t) value;
356         }
357         else {
358                 index        = ARG_CNT + pd->index;
359 #if SIZEOF_VOID_P == 8
360                 array[index] = (uint64_t) (intptr_t) value;
361 #else
362 # if WORDS_BIGENDIAN == 1
363                 array[index] = ((uint64_t) (intptr_t) value) << 32;
364 # else
365                 array[index] = (uint64_t) (intptr_t) value;
366 # endif
367 #endif
368         }
369 }
370
371
372 /* argument_vmarray_from_valist ************************************************
373
374    Creates an argument array which can be passed to asm_vm_call_method.
375    The array is created from the passed valist.
376
377    ATTENTION: This function has to be used outside the native world.
378
379 *******************************************************************************/
380
381 uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
382 {
383         methoddesc *md;
384         paramdesc  *pd;
385         typedesc   *td;
386         uint64_t   *array;
387         int32_t     i;
388         imm_union   value;
389
390         /* get the descriptors */
391
392         md = m->parseddesc;
393         pd = md->params;
394         td = md->paramtypes;
395
396         // Allocate argument array.
397         array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
398
399         /* if method is non-static fill first block and skip `this' pointer */
400
401         i = 0;
402
403         if (o != NULL) {
404                 /* the `this' pointer */
405                 argument_vmarray_store_adr(array, pd, o);
406
407                 pd++;
408                 td++;
409                 i++;
410         } 
411
412         for (; i < md->paramcount; i++, pd++, td++) {
413                 switch (td->type) {
414                 case TYPE_INT:
415                         value.i = va_arg(ap, int32_t);
416                         argument_vmarray_store_int(array, pd, value.i);
417                         break;
418
419                 case TYPE_LNG:
420                         value.l = va_arg(ap, int64_t);
421                         argument_vmarray_store_lng(array, pd, value.l);
422                         break;
423
424                 case TYPE_FLT:
425 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
426                         /* This is required to load the correct float value in
427                            assembler code. */
428
429                         value.d = (double) va_arg(ap, double);
430 #else
431                         value.f = (float) va_arg(ap, double);
432 #endif
433                         argument_vmarray_store_flt(array, pd, value.l);
434                         break;
435
436                 case TYPE_DBL:
437                         value.d = va_arg(ap, double);
438                         argument_vmarray_store_dbl(array, pd, value.l);
439                         break;
440
441                 case TYPE_ADR: 
442                         value.a = va_arg(ap, void*);
443                         argument_vmarray_store_adr(array, pd, static_cast<java_handle_t*>(value.a));
444                         break;
445                 }
446         }
447
448         return array;
449 }
450
451
452 /* argument_vmarray_from_jvalue ************************************************
453
454    Creates an argument array which can be passed to asm_vm_call_method.
455    The array is created from the passed jvalue array.
456
457    ATTENTION: This function has to be used outside the native world.
458
459 *******************************************************************************/
460
461 uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
462                                                                            const jvalue *args)
463 {
464         methoddesc *md;
465         paramdesc  *pd;
466         typedesc   *td;
467         uint64_t   *array;
468         int32_t     i;
469         int32_t     j;
470
471         /* get the descriptors */
472
473         md = m->parseddesc;
474         pd = md->params;
475         td = md->paramtypes;
476
477         /* allocate argument array */
478
479 #if defined(HAS_ADDRESS_REGISTER_FILE)
480         array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse));
481 #else
482         array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
483 #endif
484
485         /* if method is non-static fill first block and skip `this' pointer */
486
487         i = 0;
488
489         if (o != NULL) {
490                 /* the `this' pointer */
491                 argument_vmarray_store_adr(array, pd, o);
492
493                 pd++;
494                 td++;
495                 i++;
496         } 
497
498         for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
499                 switch (td->primitivetype) {
500                 case TYPE_INT:
501                         argument_vmarray_store_int(array, pd, args[j].i);
502                         break;
503
504                 case TYPE_LNG:
505                         argument_vmarray_store_lng(array, pd, args[j].j);
506                         break;
507
508                 case TYPE_FLT:
509                         argument_vmarray_store_flt(array, pd, args[j].j);
510                         break;
511
512                 case TYPE_DBL:
513                         argument_vmarray_store_dbl(array, pd, args[j].j);
514                         break;
515
516                 case TYPE_ADR: 
517                         argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
518                         break;
519                 }
520         }
521
522         return array;
523 }
524
525
526 /* argument_vmarray_from_objectarray *******************************************
527
528    Creates an argument array which can be passed to asm_vm_call_method.
529    The array is created from the passed objectarray of boxed values.
530
531    ATTENTION: This function has to be used outside the native world.
532
533    RETURN VALUE:
534       NULL.........indicates an error while creating the array
535       (-1).........no error, but an empty array
536       otherwise....array containing the argument values
537
538 *******************************************************************************/
539
540 uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
541                                                                                         java_handle_objectarray_t *params)
542 {
543         methoddesc    *md;
544         paramdesc     *pd;
545         typedesc      *td;
546         uint64_t      *array;
547         java_handle_t *param;
548         classinfo     *c;
549         int            type;
550         int32_t        i;
551         int32_t        j;
552         imm_union      value;
553
554         /* get the descriptors */
555
556         md = m->parseddesc;
557         pd = md->params;
558         td = md->paramtypes;
559
560         /* allocate argument array */
561
562         array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
563
564         /* The array can be NULL if we don't have any arguments to pass
565            and the architecture does not have any argument registers
566            (e.g. i386).  In that case we return (-1) to indicate
567            that no exception should be thrown */
568
569         if (array == NULL)
570                 array = (uint64_t *)(-1);
571
572         /* if method is non-static fill first block and skip `this' pointer */
573
574         i = 0;
575
576         if (o != NULL) {
577                 /* this pointer */
578                 argument_vmarray_store_adr(array, pd, o);
579
580                 pd++;
581                 td++;
582                 i++;
583         }
584
585         ObjectArray oa(params);
586
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 = oa.get_element(j);
591
592                 switch (td->type) {
593                 case TYPE_INT:
594                         if (param == NULL)
595                                 return NULL;
596
597                         /* convert the value according to its declared type */
598
599                         LLNI_class_get(param, c);
600                         type = Primitive::get_type_by_wrapperclass(c);
601
602                         switch (td->primitivetype) {
603                         case PRIMITIVETYPE_BOOLEAN:
604                                 switch (type) {
605                                 case PRIMITIVETYPE_BOOLEAN:
606                                         /* This type is OK. */
607                                         break;
608                                 default:
609                                         return NULL;
610                                 }
611                                 break;
612
613                         case PRIMITIVETYPE_BYTE:
614                                 switch (type) {
615                                 case PRIMITIVETYPE_BYTE:
616                                         /* This type is OK. */
617                                         break;
618                                 default:
619                                         return NULL;
620                                 }
621                                 break;
622
623                         case PRIMITIVETYPE_CHAR:
624                                 switch (type) {
625                                 case PRIMITIVETYPE_CHAR:
626                                         /* This type is OK. */
627                                         break;
628                                 default:
629                                         return NULL;
630                                 }
631                                 break;
632
633                         case PRIMITIVETYPE_SHORT:
634                                 switch (type) {
635                                 case PRIMITIVETYPE_BYTE:
636                                 case PRIMITIVETYPE_SHORT:
637                                         /* These types are OK. */
638                                         break;
639                                 default:
640                                         return NULL;
641                                 }
642                                 break;
643
644                         case PRIMITIVETYPE_INT:
645                                 switch (type) {
646                                 case PRIMITIVETYPE_BYTE:
647                                 case PRIMITIVETYPE_SHORT:
648                                 case PRIMITIVETYPE_INT:
649                                         /* These types are OK. */
650                                         break;
651                                 default:
652                                         return NULL;
653                                 }
654                                 break;
655
656                         default:
657                                 os::abort("argument_vmarray_from_objectarray: invalid type %d",
658                                                  td->primitivetype);
659                         }
660
661                         value = Primitive::unbox(param);
662                         argument_vmarray_store_int(array, pd, value.i);
663                         break;
664
665                 case TYPE_LNG:
666                         if (param == NULL)
667                                 return NULL;
668
669                         LLNI_class_get(param, c);
670                         type = Primitive::get_type_by_wrapperclass(c);
671
672                         assert(td->primitivetype == PRIMITIVETYPE_LONG);
673
674                         switch (type) {
675                         case PRIMITIVETYPE_BYTE:
676                         case PRIMITIVETYPE_SHORT:
677                         case PRIMITIVETYPE_INT:
678                         case PRIMITIVETYPE_LONG:
679                                 /* These types are OK. */
680                                 break;
681                         default:
682                                 return NULL;
683                         }
684
685                         value = Primitive::unbox(param);
686                         argument_vmarray_store_lng(array, pd, value.l);
687                         break;
688
689                 case TYPE_FLT:
690                         if (param == NULL)
691                                 return NULL;
692
693                         LLNI_class_get(param, c);
694                         type = Primitive::get_type_by_wrapperclass(c);
695
696                         assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
697
698                         switch (type) {
699                         case PRIMITIVETYPE_FLOAT:
700                                 /* This type is OK. */
701                                 break;
702                         default:
703                                 return NULL;
704                         }
705
706                         value = Primitive::unbox(param);
707                         argument_vmarray_store_flt(array, pd, value.l);
708                         break;
709
710                 case TYPE_DBL:
711                         if (param == NULL)
712                                 return NULL;
713
714                         LLNI_class_get(param, c);
715                         type = Primitive::get_type_by_wrapperclass(c);
716
717                         assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
718
719                         switch (type) {
720                         case PRIMITIVETYPE_FLOAT:
721                         case PRIMITIVETYPE_DOUBLE:
722                                 /* These types are OK. */
723                                 break;
724                         default:
725                                 return NULL;
726                         }
727
728                         value = Primitive::unbox(param);
729                         argument_vmarray_store_dbl(array, pd, value.l);
730                         break;
731                 
732                 case TYPE_ADR:
733                         if (!resolve_class_from_typedesc(td, true, true, &c))
734                                 return NULL;
735
736                         if (param != NULL) {
737                                 if (td->arraydim > 0) {
738                                         if (!builtin_arrayinstanceof(param, c))
739                                                 return NULL;
740                                 }
741                                 else {
742                                         if (!builtin_instanceof(param, c))
743                                                 return NULL;
744                                 }
745                         }
746
747                         argument_vmarray_store_adr(array, pd, param);
748                         break;
749
750                 default:
751                         os::abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
752                 }
753         }
754
755         return array;
756 }
757
758
759 /*
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  * ---------------------------------------------------------------------
764  * Local variables:
765  * mode: c++
766  * indent-tabs-mode: t
767  * c-basic-offset: 4
768  * tab-width: 4
769  * End:
770  * vim:noexpandtab:sw=4:ts=4:
771  */