1 /*------------------------------------------------------------------*/
5 /* Function - Create trampolines to invoke arbitrary functions. */
7 /* Name - Neale Ferguson. */
9 /* Date - October, 2002 */
12 /*------------------------------------------------------------------*/
14 /*------------------------------------------------------------------*/
16 /*------------------------------------------------------------------*/
18 #define PROLOG_INS 24 /* Size of emitted prolog */
19 #define CALL_INS 4 /* Size of emitted call */
20 #define EPILOG_INS 18 /* Size of emitted epilog */
24 /*========================= End of Defines =========================*/
26 /*------------------------------------------------------------------*/
28 /*------------------------------------------------------------------*/
31 # include <sys/mman.h>
32 # include <limits.h> /* for PAGESIZE */
34 # define PAGESIZE 4096
41 #include "s390x-codegen.h"
42 #include "mono/metadata/class.h"
43 #include "mono/metadata/tabledefs.h"
44 #include "mono/interpreter/interp.h"
45 #include "mono/metadata/appdomain.h"
46 #include "mono/metadata/marshal.h"
48 /*========================= End of Includes ========================*/
50 /*------------------------------------------------------------------*/
52 /*------------------------------------------------------------------*/
54 /*------------------------------------------------------------------*/
55 /* Structure used to accummulate size of stack, code, and locals */
56 /*------------------------------------------------------------------*/
64 /*========================= End of Typedefs ========================*/
66 /*------------------------------------------------------------------*/
68 /* Name - add_general */
70 /* Function - Determine code and stack size incremements for a */
73 /*------------------------------------------------------------------*/
76 add_general (guint *gr, size_data *sz, gboolean simple)
79 if (*gr >= GENERAL_REGS) {
80 sz->stack_size += sizeof(long);
86 if (*gr >= GENERAL_REGS - 1) {
87 sz->stack_size += 8 + (sz->stack_size % 8);
97 /*========================= End of Function ========================*/
99 /*------------------------------------------------------------------*/
101 /* Name - calculate_sizes */
103 /* Function - Determine the amount of space required for code */
104 /* and stack. In addition determine starting points */
105 /* for stack-based parameters, and area for struct- */
106 /* ures being returned on the stack. */
108 /*------------------------------------------------------------------*/
111 calculate_sizes (MonoMethodSignature *sig, size_data *sz,
112 gboolean string_ctor)
114 guint i, fr, gr, size;
115 guint32 simpletype, align;
120 sz->stack_size = S390_MINIMAL_STACK_SIZE;
121 sz->code_size = (PROLOG_INS + CALL_INS + EPILOG_INS);
125 add_general (&gr, sz, TRUE);
128 /*----------------------------------------------------------*/
129 /* We determine the size of the return code/stack in case we*/
130 /* need to reserve a register to be used to address a stack */
131 /* area that the callee will use. */
132 /*----------------------------------------------------------*/
134 if (sig->ret->byref || string_ctor) {
137 simpletype = sig->ret->type;
139 switch (simpletype) {
140 case MONO_TYPE_BOOLEAN:
150 case MONO_TYPE_CLASS:
151 case MONO_TYPE_OBJECT:
155 case MONO_TYPE_SZARRAY:
156 case MONO_TYPE_ARRAY:
157 case MONO_TYPE_STRING:
163 case MONO_TYPE_VALUETYPE:
164 if (sig->ret->data.klass->enumtype) {
165 simpletype = sig->ret->data.klass->enum_basetype->type;
170 size = mono_class_native_size (sig->ret->data.klass, &align);
172 size = mono_class_value_size (sig->ret->data.klass, &align);
176 /*----------------------------------*/
177 /* On S/390, structures of size 1, */
178 /* 2, 4, and 8 bytes are returned */
179 /* in (a) register(s). */
180 /*----------------------------------*/
196 g_error ("Can't handle as return value 0x%x", sig->ret->type);
200 /*----------------------------------------------------------*/
201 /* We determine the size of the parameter code and stack */
202 /* requirements by checking the types and sizes of the */
204 /*----------------------------------------------------------*/
206 for (i = 0; i < sig->param_count; ++i) {
207 if (sig->params [i]->byref) {
208 add_general (&gr, sz, TRUE);
211 simpletype = sig->params [i]->type;
213 switch (simpletype) {
214 case MONO_TYPE_BOOLEAN:
225 case MONO_TYPE_CLASS:
226 case MONO_TYPE_OBJECT:
227 case MONO_TYPE_STRING:
228 add_general (&gr, sz, TRUE);
230 case MONO_TYPE_SZARRAY:
231 add_general (&gr, sz, TRUE);
233 case MONO_TYPE_VALUETYPE:
234 if (sig->params [i]->data.klass->enumtype) {
235 simpletype = sig->params [i]->data.klass->enum_basetype->type;
239 size = mono_class_native_size (sig->params [i]->data.klass, &align);
241 size = mono_class_value_size (sig->params [i]->data.klass, &align);
242 DEBUG(printf("%d typesize: %d (%d)\n",i,size,align));
244 /*----------------------------------*/
245 /* On S/390, structures of size 1, */
246 /* 2, 4, and 8 bytes are passed in */
247 /* (a) register(s). */
248 /*----------------------------------*/
253 add_general(&gr, sz, TRUE);
256 add_general(&gr, sz, FALSE);
259 sz->local_size += (size + (size % align));
264 add_general (&gr, sz, FALSE);
267 if (fr < FLOAT_REGS) {
277 if (fr < FLOAT_REGS) {
282 sz->stack_size += 8 + (sz->stack_size % 8);
286 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
291 /* align stack size to 8 */
292 DEBUG (printf (" stack size: %d (%d)\n"
295 (sz->stack_size + 8) & ~8, sz->stack_size,
296 (sz->code_size),(sz->local_size + 8) & ~8));
297 sz->stack_size = (sz->stack_size + 8) & ~8;
298 sz->local_size = (sz->local_size + 8) & ~8;
301 /*========================= End of Function ========================*/
303 /*------------------------------------------------------------------*/
305 /* Name - emit_prolog */
307 /* Function - Create the instructions that implement the stand- */
308 /* ard function prolog according to the S/390 ABI. */
310 /*------------------------------------------------------------------*/
312 static inline guint8 *
313 emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
317 stack_size = sz->stack_size + sz->local_size;
319 /* function prolog */
320 s390_stmg(p, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
321 s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS);
322 s390_lgr (p, s390_r11, STK_BASE);
323 s390_aghi(p, STK_BASE, -stack_size);
324 s390_stg (p, s390_r11, 0, STK_BASE, 0);
326 /*-----------------------------------------*/
328 /* - address of "callme" */
329 /* - address of "retval" */
330 /* - address of "arguments" */
331 /*-----------------------------------------*/
332 s390_lgr (p, s390_r9, s390_r2);
333 s390_lgr (p, s390_r8, s390_r3);
334 s390_lgr (p, s390_r10, s390_r5);
339 /*========================= End of Function ========================*/
341 /*------------------------------------------------------------------*/
343 /* Name - emit_save_parameters */
345 /* Function - Create the instructions that load registers with */
346 /* parameters, place others on the stack according */
347 /* to the S/390 ABI. */
349 /* The resulting function takes the form: */
350 /* void func (void (*callme)(), void *retval, */
351 /* void *this_obj, stackval *arguments); */
353 /*------------------------------------------------------------------*/
355 inline static guint8*
356 emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz)
358 guint i, fr, gr, act_strs, align,
359 stack_par_pos, size, local_pos;
362 /*----------------------------------------------------------*/
363 /* If a structure on stack is being returned, reserve r2 */
364 /* to point to an area where it can be passed. */
365 /*----------------------------------------------------------*/
372 stack_par_pos = S390_MINIMAL_STACK_SIZE;
373 local_pos = sz->stack_size;
376 s390_lr (p, s390_r2 + gr, s390_r4);
381 for (i = 0; i < sig->param_count; ++i) {
382 DEBUG(printf("par: %d type: %d ref: %d\n",i,sig->params[i]->type,sig->params[i]->byref));
383 if (sig->params [i]->byref) {
384 if (gr < GENERAL_REGS) {
385 s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
388 s390_lg (p, s390_r0, 0, ARG_BASE, STKARG);
389 s390_stg(p, s390_r0, 0, STK_BASE, stack_par_pos);
390 stack_par_pos += sizeof(long);
394 simpletype = sig->params [i]->type;
396 switch (simpletype) {
397 case MONO_TYPE_BOOLEAN:
408 case MONO_TYPE_CLASS:
409 case MONO_TYPE_OBJECT:
410 case MONO_TYPE_STRING:
411 case MONO_TYPE_SZARRAY:
412 if (gr < GENERAL_REGS) {
413 s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
416 s390_lg (p, s390_r0, 0, ARG_BASE, STKARG);
417 s390_stg(p, s390_r0, 0, STK_BASE, stack_par_pos);
418 stack_par_pos += sizeof(long);
421 case MONO_TYPE_VALUETYPE:
422 if (sig->params [i]->data.klass->enumtype) {
423 simpletype = sig->params [i]->data.klass->enum_basetype->type;
427 size = mono_class_native_size (sig->params [i]->data.klass, &align);
429 size = mono_class_value_size (sig->params [i]->data.klass, &align);
430 DEBUG(printf("parStruct - size %d pinvoke: %d\n",size,sig->pinvoke));
436 if (gr < GENERAL_REGS) {
437 s390_lg (p, s390_r2 + gr, 0,ARG_BASE, STKARG);
438 s390_lgf(p, s390_r2 + gr, 0, s390_r2 + gr, 0);
441 stack_par_pos += (stack_par_pos % align);
442 s390_lg (p, s390_r10, 0,ARG_BASE, STKARG);
443 s390_lgf(p, s390_r10, 0, s390_r10, 0);
444 s390_st (p, s390_r10, 0, STK_BASE, stack_par_pos);
445 stack_par_pos += sizeof(long);
449 if (gr < GENERAL_REGS) {
450 s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
451 s390_lg (p, s390_r2 + gr, 0, s390_r2 + gr, 0);
453 stack_par_pos += (stack_par_pos % align);
454 s390_lg (p, s390_r10, 0, ARG_BASE, STKARG);
455 s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, s390_r10, 0);
456 stack_par_pos += sizeof(long long);
461 local_pos += (local_pos % align);
462 s390_lg (p, s390_r13, 0, ARG_BASE, STKARG);
463 s390_mvc (p, size, STK_BASE, local_pos, s390_r13, 0);
464 s390_la (p, s390_r13, 0, STK_BASE, local_pos);
467 local_pos += (local_pos % align);
468 s390_bras (p, s390_r13, 4);
470 s390_lg (p, s390_r1, 0, s390_r13, 0);
471 s390_lg (p, s390_r0, 0, ARG_BASE, STKARG);
472 s390_lgr (p, s390_r14, s390_r12);
473 s390_la (p, s390_r12, 0, STK_BASE, local_pos);
474 s390_lgr (p, s390_r13, s390_r1);
475 s390_mvcl (p, s390_r12, s390_r0);
476 s390_lgr (p, s390_r12, s390_r14);
477 s390_la (p, s390_r13, 0, STK_BASE, local_pos);
480 if (gr < GENERAL_REGS) {
481 s390_lgr(p, s390_r2 + gr, s390_r13);
484 s390_stg(p, s390_r13, 0, STK_BASE, stack_par_pos);
485 stack_par_pos += sizeof(long);
490 if (gr < GENERAL_REGS) {
491 s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
495 *(guint32 *) p &= ~7;
496 s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
497 stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long));
501 if (fr < FLOAT_REGS) {
502 s390_le (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
505 s390_mvc (p, sizeof(float), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
506 stack_par_pos += sizeof(float);
510 if (fr < FLOAT_REGS) {
511 s390_ld (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
515 *(guint32 *) p &= ~7;
516 s390_mvc (p, sizeof(double), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
517 stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long));
521 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
525 /*----------------------------------------------------------*/
526 /* If we're returning a structure but not in a register */
527 /* then point the result area for the called routine */
528 /*----------------------------------------------------------*/
530 s390_lg (p, s390_r2, 0, s390_r8, 0);
536 /*========================= End of Function ========================*/
538 /*------------------------------------------------------------------*/
540 /* Name - alloc_code_memory */
542 /* Function - Allocate space to place the emitted code. */
544 /*------------------------------------------------------------------*/
546 static inline guint8 *
547 alloc_code_memory (guint code_size)
552 p = g_malloc (code_size + PAGESIZE - 1);
554 /* Align to a multiple of PAGESIZE, assumed to be a power of two */
555 p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
557 p = g_malloc (code_size);
559 DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4));
564 /*========================= End of Function ========================*/
566 /*------------------------------------------------------------------*/
568 /* Name - emit_call_and_store_retval */
570 /* Function - Emit code that will implement the call to the */
571 /* desired function, and unload the result according */
572 /* to the S390 ABI for the type of value returned */
574 /*------------------------------------------------------------------*/
576 static inline guint8 *
577 emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig,
578 size_data *sz, gboolean string_ctor)
581 guint retSize, align;
584 s390_basr (p, s390_r14, s390_r9);
586 /* get return value */
587 if (sig->ret->byref || string_ctor) {
588 s390_stg(p, s390_r2, 0, s390_r8, 0);
590 simpletype = sig->ret->type;
592 switch (simpletype) {
593 case MONO_TYPE_BOOLEAN:
596 s390_stc (p, s390_r2, 0, s390_r8, 0);
601 s390_sth (p, s390_r2, 0, s390_r8, 0);
607 case MONO_TYPE_CLASS:
608 case MONO_TYPE_OBJECT:
609 case MONO_TYPE_SZARRAY:
610 case MONO_TYPE_ARRAY:
611 case MONO_TYPE_STRING:
612 s390_st (p, s390_r2, 0, s390_r8, 0);
615 s390_ste (p, s390_f0, 0, s390_r8, 0);
618 s390_std (p, s390_f0, 0, s390_r8, 0);
621 s390_stg (p, s390_r2, 0, s390_r8, 0);
623 case MONO_TYPE_VALUETYPE:
624 if (sig->ret->data.klass->enumtype) {
625 simpletype = sig->ret->data.klass->enum_basetype->type;
629 retSize = mono_class_native_size (sig->ret->data.klass, &align);
631 retSize = mono_class_value_size (sig->ret->data.klass, &align);
632 printf("Returning %d bytes for type %d (%d)\n",retSize,simpletype,sig->pinvoke);
637 s390_stc (p, s390_r2, 0, s390_r8, 0);
640 s390_sth (p, s390_r2, 0, s390_r8, 0);
643 s390_st (p, s390_r2, 0, s390_r8, 0);
646 s390_stg (p, s390_r2, 0, s390_r8, 0);
649 /*------------------------------------------*/
650 /* The callee has already placed the result */
651 /* in the required area */
652 /*------------------------------------------*/
658 g_error ("Can't handle as return value 0x%x",
666 /*========================= End of Function ========================*/
668 /*------------------------------------------------------------------*/
670 /* Name - emit_epilog */
672 /* Function - Create the instructions that implement the stand- */
673 /* ard function epilog according to the S/390 ABI. */
675 /*------------------------------------------------------------------*/
677 static inline guint8 *
678 emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
680 /* function epilog */
681 s390_lg (p, STK_BASE, 0, STK_BASE, 0);
682 s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET);
683 s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
684 s390_br (p, s390_r4);
689 /*========================= End of Function ========================*/
691 /*------------------------------------------------------------------*/
693 /* Name - mono_arch_create_trampoline. */
695 /* Function - Create the code that will allow a mono method to */
696 /* invoke a system subroutine. */
698 /*------------------------------------------------------------------*/
701 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
703 guint8 *p, *code_buffer;
706 DEBUG (printf ("\nPInvoke [start emiting]\n"));
707 calculate_sizes (sig, &sz, string_ctor);
709 p = code_buffer = alloc_code_memory (sz.code_size);
710 p = emit_prolog (p, sig, &sz);
711 p = emit_save_parameters (p, sig, &sz);
712 p = emit_call_and_store_retval (p, sig, &sz, string_ctor);
713 p = emit_epilog (p, sig, &sz);
716 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
717 g_error ("Cannot mprotect trampoline\n");
721 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
723 DEBUG (printf ("PInvoke [end emiting]\n"));
725 return (MonoPIFunc) code_buffer;
728 /*========================= End of Function ========================*/
730 /*------------------------------------------------------------------*/
732 /* Name - mono_arch_create_method_pointer */
734 /* Function - Returns a pointer to a native function that can */
735 /* be used to call the specified method. */
737 /* The function created will receive the arguments */
738 /* according to the calling convention specified in */
741 /* This function works by creating a MonoInvocation */
742 /* structure, filling the fields in and calling */
743 /* ves_exec_method() on it. */
747 /* mono_arch_create_method_pointer (MonoMethod *method) */
748 /* create the unmanaged->managed wrapper */
749 /* register it with mono_jit_info_table_add() */
751 /* What does the unmanaged->managed wrapper do? */
752 /* allocate a MonoInvocation structure (inv) on the stack */
753 /* allocate an array of stackval on the stack with length = */
754 /* method->signature->param_count + 1 [call it stack_args] */
755 /* set inv->ex, inv->ex_handler, inv->parent to NULL */
756 /* set inv->method to method */
757 /* if method is an instance method, set inv->obj to the */
758 /* 'this' argument (the first argument) else set to NULL */
759 /* for each argument to the method call: */
760 /* stackval_from_data (sig->params[i], &stack_args[i], */
761 /* arg, sig->pinvoke); */
764 /* sig - is method->signature */
765 /* &stack_args[i] - is the pointer to the ith element */
766 /* in the stackval array */
767 /* arg - is a pointer to the argument re- */
768 /* ceived by the function according */
769 /* to the call convention. If it */
770 /* gets passed in a register, save */
771 /* on the stack first. */
773 /* set inv->retval to the address of the last element of */
774 /* stack_args [recall we allocated param_count+1 of them] */
775 /* call ves_exec_method(inv) */
776 /* copy the returned value from inv->retval where the calling */
777 /* convention expects to find it on return from the wrap- */
778 /* per [if it's a structure, use stackval_to_data] */
780 /*------------------------------------------------------------------*/
783 mono_arch_create_method_pointer (MonoMethod *method)
785 MonoMethodSignature *sig;
787 guint8 *p, *code_buffer;
788 guint i, align = 0, simple_type, retSize, reg_save = 0,
789 stackval_arg_pos, local_pos, float_pos,
790 local_start, reg_param = 0, stack_param,
791 this_flag, arg_pos, fpr_param, parSize;
794 int *vtbuf, cpos, vt_cur;
797 sz.stack_size = 1024;
802 sig = method->signature;
804 p = code_buffer = g_malloc (sz.code_size);
806 DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n",
809 /*----------------------------------------------------------*/
811 /*----------------------------------------------------------*/
812 s390_stmg(p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
813 s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS);
814 s390_lgr (p, s390_r0, STK_BASE);
815 s390_aghi(p, STK_BASE, -(sz.stack_size+MINV_POS));
816 s390_stg (p, s390_r0, 0, STK_BASE, 0);
817 s390_la (p, s390_r8, 0, STK_BASE, 4);
818 s390_lgr (p, s390_r10, s390_r8);
819 s390_lghi(p, s390_r9, sz.stack_size+92);
820 s390_lghi(p, s390_r11, 0);
821 s390_mvcl(p, s390_r8, s390_r10);
823 /*----------------------------------------------------------*/
824 /* Let's fill MonoInvocation - first zero some fields */
825 /*----------------------------------------------------------*/
826 s390_lghi (p, s390_r0, 0);
827 s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)));
828 s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)));
829 s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)));
830 s390_lghi (p, s390_r0, 1);
831 s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap)));
833 /*----------------------------------------------------------*/
834 /* set method pointer */
835 /*----------------------------------------------------------*/
836 s390_bras (p, s390_r13, 4);
837 s390_llong(p, method);
838 s390_lg (p, s390_r0, 0, s390_r13, 0);
839 s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)));
841 local_start = local_pos = MINV_POS +
842 sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
843 this_flag = (sig->hasthis ? 1 : 0);
845 /*----------------------------------------------------------*/
846 /* if we are returning a structure, checks it's length to */
847 /* see if there's a "hidden" parameter that points to the */
848 /* area. If necessary save this hidden parameter for later */
849 /*----------------------------------------------------------*/
850 if (MONO_TYPE_ISSTRUCT(sig->ret)) {
852 retSize = mono_class_native_size (sig->ret->data.klass, &align);
854 retSize = mono_class_value_size (sig->ret->data.klass, &align);
865 s390_lgr(p, s390_r8, s390_r2);
873 s390_stg (p, s390_r2 + reg_save, 0, STK_BASE,
874 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
877 s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, local_pos);
878 local_pos += sizeof(int);
879 s390_stg (p, s390_r0, 0, STK_BASE,
880 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
883 s390_stmg (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos);
884 local_pos += 4 * sizeof(long);
885 float_pos = local_pos;
886 s390_std (p, s390_f0, 0, STK_BASE, local_pos);
887 local_pos += sizeof(double);
888 s390_std (p, s390_f2, 0, STK_BASE, local_pos);
889 local_pos += sizeof(double);
891 /*----------------------------------------------------------*/
892 /* prepare space for valuetypes */
893 /*----------------------------------------------------------*/
895 vtbuf = alloca (sizeof(int)*sig->param_count);
897 for (i = 0; i < sig->param_count; i++) {
898 MonoType *type = sig->params [i];
900 DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref));
901 if (type->type == MONO_TYPE_VALUETYPE) {
902 MonoClass *klass = type->data.klass;
907 size = mono_class_native_size (klass, &align);
909 cpos &= ~(align - 1);
919 /*----------------------------------------------------------*/
920 /* set MonoInvocation::stack_args */
921 /*----------------------------------------------------------*/
922 stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
923 s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos);
924 s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)));
926 /*----------------------------------------------------------*/
927 /* add stackval arguments */
928 /*----------------------------------------------------------*/
929 for (i = 0; i < sig->param_count; ++i) {
930 if (sig->params [i]->byref) {
931 ADD_ISTACK_PARM(0, 1);
933 simple_type = sig->params [i]->type;
935 switch (simple_type) {
937 ADD_ISTACK_PARM(-1, 2);
945 case MONO_TYPE_VALUETYPE:
946 if (sig->params [i]->data.klass->enumtype) {
947 simple_type = sig->params [i]->data.klass->enum_basetype->type;
951 parSize = mono_class_native_size (sig->params [i]->data.klass, &align);
953 parSize = mono_class_value_size (sig->params [i]->data.klass, &align);
959 ADD_PSTACK_PARM(0, 1);
962 ADD_PSTACK_PARM(-1, 2);
969 ADD_ISTACK_PARM(0, 1);
973 if (vtbuf [i] >= 0) {
974 s390_la (p, s390_r3, 0, STK_BASE, vt_cur);
975 s390_stg (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
976 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
979 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
982 /*--------------------------------------*/
983 /* Load the parameter registers for the */
984 /* call to stackval_from_data */
985 /*--------------------------------------*/
986 s390_bras (p, s390_r13, 8);
987 s390_llong(p, sig->params [i]);
988 s390_llong(p, sig->pinvoke);
989 s390_llong(p, stackval_from_data);
990 s390_lg (p, s390_r2, 0, s390_r13, 0);
991 s390_lg (p, s390_r5, 0, s390_r13, 4);
992 s390_lg (p, s390_r1, 0, s390_r13, 8);
993 s390_basr (p, s390_r14, s390_r1);
995 stackval_arg_pos += sizeof(stackval);
997 /* fixme: alignment */
998 DEBUG (printf ("arg_pos %d --> ", arg_pos));
1000 arg_pos += mono_type_native_stack_size (sig->params [i], &align);
1002 arg_pos += mono_type_stack_size (sig->params [i], &align);
1004 DEBUG (printf ("%d\n", stackval_arg_pos));
1007 /*----------------------------------------------------------*/
1008 /* Set return area pointer. */
1009 /*----------------------------------------------------------*/
1010 s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos);
1011 s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1012 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
1013 MonoClass *klass = sig->ret->data.klass;
1014 if (!klass->enumtype) {
1015 s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval));
1016 s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos);
1017 stackval_arg_pos += sizeof(stackval);
1021 /*----------------------------------------------------------*/
1022 /* call ves_exec_method */
1023 /*----------------------------------------------------------*/
1024 s390_bras (p, s390_r13, 4);
1025 s390_llong(p, ves_exec_method);
1026 s390_lg (p, s390_r1, 0, s390_r13, 0);
1027 s390_la (p, s390_r2, 0, STK_BASE, MINV_POS);
1028 s390_basr (p, s390_r14, s390_r1);
1030 /*----------------------------------------------------------*/
1031 /* move retval from stackval to proper place (r3/r4/...) */
1032 /*----------------------------------------------------------*/
1033 DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref));
1034 if (sig->ret->byref) {
1035 DEBUG (printf ("ret by ref\n"));
1036 s390_stg(p, s390_r2, 0, s390_r10, 0);
1039 switch (sig->ret->type) {
1040 case MONO_TYPE_VOID:
1042 case MONO_TYPE_BOOLEAN:
1044 s390_lghi(p, s390_r2, 0);
1045 s390_ic (p, s390_r2, 0, s390_r10, 0);
1049 s390_lh (p, s390_r2, 0,s390_r10, 0);
1055 s390_lgf(p, s390_r2, 0, s390_r10, 0);
1057 case MONO_TYPE_OBJECT:
1058 case MONO_TYPE_STRING:
1059 case MONO_TYPE_CLASS:
1061 s390_lg (p, s390_r2, 0, s390_r10, 0);
1064 s390_le (p, s390_f0, 0, s390_r10, 0);
1067 s390_ld (p, s390_f0, 0, s390_r10, 0);
1069 case MONO_TYPE_VALUETYPE:
1070 if (sig->ret->data.klass->enumtype) {
1071 simpletype = sig->ret->data.klass->enum_basetype->type;
1074 /*---------------------------------*/
1075 /* Call stackval_to_data to return */
1077 /*---------------------------------*/
1078 s390_bras (p, s390_r13, 8);
1079 s390_llong(p, sig->ret);
1080 s390_llong(p, sig->pinvoke);
1081 s390_llong(p, stackval_to_data);
1082 s390_lg (p, s390_r2, 0, s390_r13, 0);
1083 s390_lg (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1085 /*------------------------------------------*/
1086 /* Get stackval_to_data to set result area */
1087 /*------------------------------------------*/
1088 s390_lgr (p, s390_r4, s390_r8);
1090 /*------------------------------------------*/
1091 /* Give stackval_to_data a temp result area */
1092 /*------------------------------------------*/
1093 s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos);
1095 s390_lg (p, s390_r5, 0,s390_r13, 4);
1096 s390_lg (p, s390_r1, 0, s390_r13, 8);
1097 s390_basr (p, s390_r14, s390_r1);
1102 s390_lghi(p, s390_r2, 0);
1103 s390_ic (p, s390_r2, 0, s390_r10, 0);
1106 s390_lh (p, s390_r2, 0, s390_r10, 0);
1109 s390_lgf(p, s390_r2, 0, s390_r10, 0);
1112 s390_lg (p, s390_r2, 0, s390_r10, 0);
1115 /*-------------------------------------------------*/
1116 /* stackval_to_data has placed data in result area */
1117 /*-------------------------------------------------*/
1121 g_error ("Type 0x%x not handled yet in thunk creation",
1127 /*----------------------------------------------------------*/
1129 /*----------------------------------------------------------*/
1130 s390_lg (p, STK_BASE, 0, STK_BASE, 0);
1131 s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET);
1132 s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
1133 s390_br (p, s390_r4);
1135 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
1137 DEBUG (printf ("Delegate [end emiting]\n"));
1139 ji = g_new0 (MonoJitInfo, 1);
1140 ji->method = method;
1141 ji->code_size = p - code_buffer;
1142 ji->code_start = code_buffer;
1144 mono_jit_info_table_add (mono_get_root_domain (), ji);
1146 return ji->code_start;
1149 /*========================= End of Function ========================*/