1 /*------------------------------------------------------------------*/
2 /* */
3 /* Name - tramp.c */
4 /* */
5 /* Function - Create trampolines to invoke arbitrary functions. */
6 /* */
7 /* Name - Neale Ferguson. */
8 /* */
9 /* Date - October, 2002 */
10 /* */
11 /* */
12 /*------------------------------------------------------------------*/
13
14 /*------------------------------------------------------------------*/
15 /* D e f i n e s */
16 /*------------------------------------------------------------------*/
17
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 */
21
22 #define DEBUG(x)
23
24 /*========================= End of Defines =========================*/
25
26 /*------------------------------------------------------------------*/
27 /* I n c l u d e s */
28 /*------------------------------------------------------------------*/
29
30 #ifdef NEED_MPROTECT
31 # include <sys/mman.h>
32 # include <limits.h> /* for PAGESIZE */
33 # ifndef PAGESIZE
34 # define PAGESIZE 4096
35 # endif
36 #endif
37
38 #include "config.h"
39 #include <stdlib.h>
40 #include <string.h>
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"
47
48 /*========================= End of Includes ========================*/
49
50 /*------------------------------------------------------------------*/
51 /* T y p e d e f s */
52 /*------------------------------------------------------------------*/
53
54 /*------------------------------------------------------------------*/
55 /* Structure used to accummulate size of stack, code, and locals */
56 /*------------------------------------------------------------------*/
57 typedef struct {
58 guint stack_size,
59 local_size,
60 code_size,
61 retStruct;
62 } size_data;
63
64 /*========================= End of Typedefs ========================*/
65
66 /*------------------------------------------------------------------*/
67 /* */
68 /* Name - add_general */
69 /* */
70 /* Function - Determine code and stack size incremements for a */
71 /* parameter. */
72 /* */
73 /*------------------------------------------------------------------*/
74
75 static void inline
add_general(guint * gr,size_data * sz,gboolean simple)76 add_general (guint *gr, size_data *sz, gboolean simple)
77 {
78 if (simple) {
79 if (*gr >= GENERAL_REGS) {
80 sz->stack_size += sizeof(long);
81 sz->code_size += 12;
82 } else {
83 sz->code_size += 8;
84 }
85 } else {
86 if (*gr >= GENERAL_REGS - 1) {
87 sz->stack_size += 8 + (sz->stack_size % 8);
88 sz->code_size += 10;
89 } else {
90 sz->code_size += 8;
91 }
92 (*gr) ++;
93 }
94 (*gr) ++;
95 }
96
97 /*========================= End of Function ========================*/
98
99 /*------------------------------------------------------------------*/
100 /* */
101 /* Name - calculate_sizes */
102 /* */
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. */
107 /* */
108 /*------------------------------------------------------------------*/
109
110 static void inline
calculate_sizes(MonoMethodSignature * sig,size_data * sz,gboolean string_ctor)111 calculate_sizes (MonoMethodSignature *sig, size_data *sz,
112 gboolean string_ctor)
113 {
114 guint i, fr, gr, size;
115 guint32 simpletype, align;
116
117 fr = 0;
118 gr = 2;
119 sz->retStruct = 0;
120 sz->stack_size = S390_MINIMAL_STACK_SIZE;
121 sz->code_size = (PROLOG_INS + CALL_INS + EPILOG_INS);
122 sz->local_size = 0;
123
124 if (sig->hasthis) {
125 add_general (&gr, sz, TRUE);
126 }
127
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 /*----------------------------------------------------------*/
133
134 if (sig->ret->byref || string_ctor) {
135 sz->code_size += 8;
136 } else {
137 simpletype = sig->ret->type;
138 enum_retvalue:
139 switch (simpletype) {
140 case MONO_TYPE_BOOLEAN:
141 case MONO_TYPE_I1:
142 case MONO_TYPE_U1:
143 case MONO_TYPE_I2:
144 case MONO_TYPE_U2:
145 case MONO_TYPE_CHAR:
146 case MONO_TYPE_I4:
147 case MONO_TYPE_U4:
148 case MONO_TYPE_I:
149 case MONO_TYPE_U:
150 case MONO_TYPE_CLASS:
151 case MONO_TYPE_OBJECT:
152 case MONO_TYPE_R4:
153 case MONO_TYPE_R8:
154 case MONO_TYPE_PTR:
155 case MONO_TYPE_SZARRAY:
156 case MONO_TYPE_ARRAY:
157 case MONO_TYPE_STRING:
158 sz->code_size += 4;
159 break;
160 case MONO_TYPE_I8:
161 sz->code_size += 4;
162 break;
163 case MONO_TYPE_VALUETYPE:
164 if (sig->ret->data.klass->enumtype) {
165 simpletype = sig->ret->data.klass->enum_basetype->type;
166 goto enum_retvalue;
167 }
168 gr++;
169 if (sig->pinvoke)
170 size = mono_class_native_size (sig->ret->data.klass, &align);
171 else
172 size = mono_class_value_size (sig->ret->data.klass, &align);
173 if (align > 1)
174 sz->code_size += 10;
175 switch (size) {
176 /*----------------------------------*/
177 /* On S/390, structures of size 1, */
178 /* 2, 4, and 8 bytes are returned */
179 /* in (a) register(s). */
180 /*----------------------------------*/
181 case 1:
182 case 2:
183 case 4:
184 case 8:
185 sz->code_size += 16;
186 sz->stack_size += 4;
187 break;
188 default:
189 sz->retStruct = 1;
190 sz->code_size += 32;
191 }
192 break;
193 case MONO_TYPE_VOID:
194 break;
195 default:
196 g_error ("Can't handle as return value 0x%x", sig->ret->type);
197 }
198 }
199
200 /*----------------------------------------------------------*/
201 /* We determine the size of the parameter code and stack */
202 /* requirements by checking the types and sizes of the */
203 /* parameters. */
204 /*----------------------------------------------------------*/
205
206 for (i = 0; i < sig->param_count; ++i) {
207 if (sig->params [i]->byref) {
208 add_general (&gr, sz, TRUE);
209 continue;
210 }
211 simpletype = sig->params [i]->type;
212 enum_calc_size:
213 switch (simpletype) {
214 case MONO_TYPE_BOOLEAN:
215 case MONO_TYPE_CHAR:
216 case MONO_TYPE_I1:
217 case MONO_TYPE_U1:
218 case MONO_TYPE_I2:
219 case MONO_TYPE_U2:
220 case MONO_TYPE_I4:
221 case MONO_TYPE_U4:
222 case MONO_TYPE_I:
223 case MONO_TYPE_U:
224 case MONO_TYPE_PTR:
225 case MONO_TYPE_CLASS:
226 case MONO_TYPE_OBJECT:
227 case MONO_TYPE_STRING:
228 add_general (&gr, sz, TRUE);
229 break;
230 case MONO_TYPE_SZARRAY:
231 add_general (&gr, sz, TRUE);
232 break;
233 case MONO_TYPE_VALUETYPE:
234 if (sig->params [i]->data.klass->enumtype) {
235 simpletype = sig->params [i]->data.klass->enum_basetype->type;
236 goto enum_calc_size;
237 }
238 if (sig->pinvoke)
239 size = mono_class_native_size (sig->params [i]->data.klass, &align);
240 else
241 size = mono_class_value_size (sig->params [i]->data.klass, &align);
242 DEBUG(printf("%d typesize: %d (%d)\n",i,size,align));
243 switch (size) {
244 /*----------------------------------*/
245 /* On S/390, structures of size 1, */
246 /* 2, 4, and 8 bytes are passed in */
247 /* (a) register(s). */
248 /*----------------------------------*/
249 case 0:
250 case 1:
251 case 2:
252 case 4:
253 add_general(&gr, sz, TRUE);
254 break;
255 case 8:
256 add_general(&gr, sz, FALSE);
257 break;
258 default:
259 sz->local_size += (size + (size % align));
260 sz->code_size += 40;
261 }
262 break;
263 case MONO_TYPE_I8:
264 add_general (&gr, sz, FALSE);
265 break;
266 case MONO_TYPE_R4:
267 if (fr < FLOAT_REGS) {
268 sz->code_size += 4;
269 fr++;
270 }
271 else {
272 sz->code_size += 4;
273 sz->stack_size += 8;
274 }
275 break;
276 case MONO_TYPE_R8:
277 if (fr < FLOAT_REGS) {
278 sz->code_size += 4;
279 fr++;
280 } else {
281 sz->code_size += 4;
282 sz->stack_size += 8 + (sz->stack_size % 8);
283 }
284 break;
285 default:
286 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
287 }
288 }
289
290
291 /* align stack size to 8 */
292 DEBUG (printf (" stack size: %d (%d)\n"
293 " code size: %d\n"
294 " local size: %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;
299 }
300
301 /*========================= End of Function ========================*/
302
303 /*------------------------------------------------------------------*/
304 /* */
305 /* Name - emit_prolog */
306 /* */
307 /* Function - Create the instructions that implement the stand- */
308 /* ard function prolog according to the S/390 ABI. */
309 /* */
310 /*------------------------------------------------------------------*/
311
312 static inline guint8 *
emit_prolog(guint8 * p,MonoMethodSignature * sig,size_data * sz)313 emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
314 {
315 guint stack_size;
316
317 stack_size = sz->stack_size + sz->local_size;
318
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);
325
326 /*-----------------------------------------*/
327 /* Save: */
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);
335
336 return p;
337 }
338
339 /*========================= End of Function ========================*/
340
341 /*------------------------------------------------------------------*/
342 /* */
343 /* Name - emit_save_parameters */
344 /* */
345 /* Function - Create the instructions that load registers with */
346 /* parameters, place others on the stack according */
347 /* to the S/390 ABI. */
348 /* */
349 /* The resulting function takes the form: */
350 /* void func (void (*callme)(), void *retval, */
351 /* void *this_obj, stackval *arguments); */
352 /* */
353 /*------------------------------------------------------------------*/
354
355 inline static guint8*
emit_save_parameters(guint8 * p,MonoMethodSignature * sig,size_data * sz)356 emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz)
357 {
358 guint i, fr, gr, act_strs, align,
359 stack_par_pos, size, local_pos;
360 guint32 simpletype;
361
362 /*----------------------------------------------------------*/
363 /* If a structure on stack is being returned, reserve r2 */
364 /* to point to an area where it can be passed. */
365 /*----------------------------------------------------------*/
366 if (sz->retStruct)
367 gr = 1;
368 else
369 gr = 0;
370 fr = 0;
371 act_strs = 0;
372 stack_par_pos = S390_MINIMAL_STACK_SIZE;
373 local_pos = sz->stack_size;
374
375 if (sig->hasthis) {
376 s390_lr (p, s390_r2 + gr, s390_r4);
377 gr++;
378 }
379
380 act_strs = 0;
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);
386 gr ++;
387 } else {
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);
391 }
392 continue;
393 }
394 simpletype = sig->params [i]->type;
395 enum_calc_size:
396 switch (simpletype) {
397 case MONO_TYPE_BOOLEAN:
398 case MONO_TYPE_I1:
399 case MONO_TYPE_U1:
400 case MONO_TYPE_I2:
401 case MONO_TYPE_U2:
402 case MONO_TYPE_CHAR:
403 case MONO_TYPE_I4:
404 case MONO_TYPE_U4:
405 case MONO_TYPE_I:
406 case MONO_TYPE_U:
407 case MONO_TYPE_PTR:
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);
414 gr ++;
415 } else {
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);
419 }
420 break;
421 case MONO_TYPE_VALUETYPE:
422 if (sig->params [i]->data.klass->enumtype) {
423 simpletype = sig->params [i]->data.klass->enum_basetype->type;
424 goto enum_calc_size;
425 }
426 if (sig->pinvoke)
427 size = mono_class_native_size (sig->params [i]->data.klass, &align);
428 else
429 size = mono_class_value_size (sig->params [i]->data.klass, &align);
430 DEBUG(printf("parStruct - size %d pinvoke: %d\n",size,sig->pinvoke));
431 switch (size) {
432 case 0:
433 case 1:
434 case 2:
435 case 4:
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);
439 gr++;
440 } else {
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);
446 }
447 break;
448 case 8:
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);
452 } else {
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);
457 }
458 break;
459 default:
460 if (size <= 256) {
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);
465 local_pos += size;
466 } else {
467 local_pos += (local_pos % align);
468 s390_bras (p, s390_r13, 4);
469 s390_llong(p, size);
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);
478 local_pos += size;
479 }
480 if (gr < GENERAL_REGS) {
481 s390_lgr(p, s390_r2 + gr, s390_r13);
482 gr++;
483 } else {
484 s390_stg(p, s390_r13, 0, STK_BASE, stack_par_pos);
485 stack_par_pos += sizeof(long);
486 }
487 }
488 break;
489 case MONO_TYPE_I8:
490 if (gr < GENERAL_REGS) {
491 s390_lg (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
492 gr += 2;
493 } else {
494 *(guint32 *) p += 7;
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));
498 }
499 break;
500 case MONO_TYPE_R4:
501 if (fr < FLOAT_REGS) {
502 s390_le (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
503 fr++;
504 } else {
505 s390_mvc (p, sizeof(float), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
506 stack_par_pos += sizeof(float);
507 }
508 break;
509 case MONO_TYPE_R8:
510 if (fr < FLOAT_REGS) {
511 s390_ld (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
512 fr++;
513 } else {
514 *(guint32 *) p += 7;
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));
518 }
519 break;
520 default:
521 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
522 }
523 }
524
525 /*----------------------------------------------------------*/
526 /* If we're returning a structure but not in a register */
527 /* then point the result area for the called routine */
528 /*----------------------------------------------------------*/
529 if (sz->retStruct) {
530 s390_lg (p, s390_r2, 0, s390_r8, 0);
531 }
532
533 return p;
534 }
535
536 /*========================= End of Function ========================*/
537
538 /*------------------------------------------------------------------*/
539 /* */
540 /* Name - alloc_code_memory */
541 /* */
542 /* Function - Allocate space to place the emitted code. */
543 /* */
544 /*------------------------------------------------------------------*/
545
546 static inline guint8 *
alloc_code_memory(guint code_size)547 alloc_code_memory (guint code_size)
548 {
549 guint8 *p;
550
551 #ifdef NEED_MPROTECT
552 p = g_malloc (code_size + PAGESIZE - 1);
553
554 /* Align to a multiple of PAGESIZE, assumed to be a power of two */
555 p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
556 #else
557 p = g_malloc (code_size);
558 #endif
559 DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4));
560
561 return p;
562 }
563
564 /*========================= End of Function ========================*/
565
566 /*------------------------------------------------------------------*/
567 /* */
568 /* Name - emit_call_and_store_retval */
569 /* */
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 */
573 /* */
574 /*------------------------------------------------------------------*/
575
576 static inline guint8 *
emit_call_and_store_retval(guint8 * p,MonoMethodSignature * sig,size_data * sz,gboolean string_ctor)577 emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig,
578 size_data *sz, gboolean string_ctor)
579 {
580 guint32 simpletype;
581 guint retSize, align;
582
583 /* call "callme" */
584 s390_basr (p, s390_r14, s390_r9);
585
586 /* get return value */
587 if (sig->ret->byref || string_ctor) {
588 s390_stg(p, s390_r2, 0, s390_r8, 0);
589 } else {
590 simpletype = sig->ret->type;
591 enum_retvalue:
592 switch (simpletype) {
593 case MONO_TYPE_BOOLEAN:
594 case MONO_TYPE_I1:
595 case MONO_TYPE_U1:
596 s390_stc (p, s390_r2, 0, s390_r8, 0);
597 break;
598 case MONO_TYPE_I2:
599 case MONO_TYPE_U2:
600 case MONO_TYPE_CHAR:
601 s390_sth (p, s390_r2, 0, s390_r8, 0);
602 break;
603 case MONO_TYPE_I4:
604 case MONO_TYPE_U4:
605 case MONO_TYPE_I:
606 case MONO_TYPE_U:
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);
613 break;
614 case MONO_TYPE_R4:
615 s390_ste (p, s390_f0, 0, s390_r8, 0);
616 break;
617 case MONO_TYPE_R8:
618 s390_std (p, s390_f0, 0, s390_r8, 0);
619 break;
620 case MONO_TYPE_I8:
621 s390_stg (p, s390_r2, 0, s390_r8, 0);
622 break;
623 case MONO_TYPE_VALUETYPE:
624 if (sig->ret->data.klass->enumtype) {
625 simpletype = sig->ret->data.klass->enum_basetype->type;
626 goto enum_retvalue;
627 }
628 if (sig->pinvoke)
629 retSize = mono_class_native_size (sig->ret->data.klass, &align);
630 else
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);
633 switch(retSize) {
634 case 0:
635 break;
636 case 1:
637 s390_stc (p, s390_r2, 0, s390_r8, 0);
638 break;
639 case 2:
640 s390_sth (p, s390_r2, 0, s390_r8, 0);
641 break;
642 case 4:
643 s390_st (p, s390_r2, 0, s390_r8, 0);
644 break;
645 case 8:
646 s390_stg (p, s390_r2, 0, s390_r8, 0);
647 break;
648 default: ;
649 /*------------------------------------------*/
650 /* The callee has already placed the result */
651 /* in the required area */
652 /*------------------------------------------*/
653 }
654 break;
655 case MONO_TYPE_VOID:
656 break;
657 default:
658 g_error ("Can't handle as return value 0x%x",
659 sig->ret->type);
660 }
661 }
662
663 return p;
664 }
665
666 /*========================= End of Function ========================*/
667
668 /*------------------------------------------------------------------*/
669 /* */
670 /* Name - emit_epilog */
671 /* */
672 /* Function - Create the instructions that implement the stand- */
673 /* ard function epilog according to the S/390 ABI. */
674 /* */
675 /*------------------------------------------------------------------*/
676
677 static inline guint8 *
emit_epilog(guint8 * p,MonoMethodSignature * sig,size_data * sz)678 emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
679 {
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);
685
686 return p;
687 }
688
689 /*========================= End of Function ========================*/
690
691 /*------------------------------------------------------------------*/
692 /* */
693 /* Name - mono_arch_create_trampoline. */
694 /* */
695 /* Function - Create the code that will allow a mono method to */
696 /* invoke a system subroutine. */
697 /* */
698 /*------------------------------------------------------------------*/
699
700 MonoPIFunc
mono_arch_create_trampoline(MonoMethodSignature * sig,gboolean string_ctor)701 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
702 {
703 guint8 *p, *code_buffer;
704 size_data sz;
705
706 DEBUG (printf ("\nPInvoke [start emiting]\n"));
707 calculate_sizes (sig, &sz, string_ctor);
708
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);
714
715 #ifdef NEED_MPROTECT
716 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
717 g_error ("Cannot mprotect trampoline\n");
718 }
719 #endif
720
721 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
722
723 DEBUG (printf ("PInvoke [end emiting]\n"));
724
725 return (MonoPIFunc) code_buffer;
726 }
727
728 /*========================= End of Function ========================*/
729
730 /*------------------------------------------------------------------*/
731 /* */
732 /* Name - mono_arch_create_method_pointer */
733 /* */
734 /* Function - Returns a pointer to a native function that can */
735 /* be used to call the specified method. */
736 /* */
737 /* The function created will receive the arguments */
738 /* according to the calling convention specified in */
739 /* in the method. */
740 /* */
741 /* This function works by creating a MonoInvocation */
742 /* structure, filling the fields in and calling */
743 /* ves_exec_method() on it. */
744 /* */
745 /* Logic: */
746 /* ------ */
747 /* mono_arch_create_method_pointer (MonoMethod *method) */
748 /* create the unmanaged->managed wrapper */
749 /* register it with mono_jit_info_table_add() */
750 /* */
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); */
762 /* Where: */
763 /* ------ */
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. */
772 /* */
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] */
779 /* */
780 /*------------------------------------------------------------------*/
781
782 void *
mono_arch_create_method_pointer(MonoMethod * method)783 mono_arch_create_method_pointer (MonoMethod *method)
784 {
785 MonoMethodSignature *sig;
786 MonoJitInfo *ji;
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;
792 guint32 simpletype;
793 size_data sz;
794 int *vtbuf, cpos, vt_cur;
795
796 sz.code_size = 1024;
797 sz.stack_size = 1024;
798 stack_param = 0;
799 fpr_param = 0;
800 arg_pos = 0;
801
802 sig = method->signature;
803
804 p = code_buffer = g_malloc (sz.code_size);
805
806 DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n",
807 method->name,p));
808
809 /*----------------------------------------------------------*/
810 /* prolog */
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);
822
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)));
832
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)));
840
841 local_start = local_pos = MINV_POS +
842 sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
843 this_flag = (sig->hasthis ? 1 : 0);
844
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)) {
851 if (sig->pinvoke)
852 retSize = mono_class_native_size (sig->ret->data.klass, &align);
853 else
854 retSize = mono_class_value_size (sig->ret->data.klass, &align);
855 switch(retSize) {
856 case 0:
857 case 1:
858 case 2:
859 case 4:
860 case 8:
861 sz.retStruct = 0;
862 break;
863 default:
864 sz.retStruct = 1;
865 s390_lgr(p, s390_r8, s390_r2);
866 reg_save = 1;
867 }
868 } else {
869 reg_save = 0;
870 }
871
872 if (this_flag) {
873 s390_stg (p, s390_r2 + reg_save, 0, STK_BASE,
874 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
875 reg_param++;
876 } else {
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)));
881 }
882
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);
890
891 /*----------------------------------------------------------*/
892 /* prepare space for valuetypes */
893 /*----------------------------------------------------------*/
894 vt_cur = local_pos;
895 vtbuf = alloca (sizeof(int)*sig->param_count);
896 cpos = 0;
897 for (i = 0; i < sig->param_count; i++) {
898 MonoType *type = sig->params [i];
899 vtbuf [i] = -1;
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;
903 gint size;
904
905 if (klass->enumtype)
906 continue;
907 size = mono_class_native_size (klass, &align);
908 cpos += align - 1;
909 cpos &= ~(align - 1);
910 vtbuf [i] = cpos;
911 cpos += size;
912 }
913 }
914 cpos += 3;
915 cpos &= ~3;
916
917 local_pos += cpos;
918
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)));
925
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);
932 } else {
933 simple_type = sig->params [i]->type;
934 enum_savechk:
935 switch (simple_type) {
936 case MONO_TYPE_I8:
937 ADD_ISTACK_PARM(-1, 2);
938 break;
939 case MONO_TYPE_R4:
940 ADD_RSTACK_PARM(1);
941 break;
942 case MONO_TYPE_R8:
943 ADD_RSTACK_PARM(2);
944 break;
945 case MONO_TYPE_VALUETYPE:
946 if (sig->params [i]->data.klass->enumtype) {
947 simple_type = sig->params [i]->data.klass->enum_basetype->type;
948 goto enum_savechk;
949 }
950 if (sig->pinvoke)
951 parSize = mono_class_native_size (sig->params [i]->data.klass, &align);
952 else
953 parSize = mono_class_value_size (sig->params [i]->data.klass, &align);
954 switch(parSize) {
955 case 0:
956 case 1:
957 case 2:
958 case 4:
959 ADD_PSTACK_PARM(0, 1);
960 break;
961 case 8:
962 ADD_PSTACK_PARM(-1, 2);
963 break;
964 default:
965 ADD_TSTACK_PARM;
966 }
967 break;
968 default:
969 ADD_ISTACK_PARM(0, 1);
970 }
971 }
972
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);
977 vt_cur += vtbuf [i];
978 } else {
979 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
980 }
981
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);
994
995 stackval_arg_pos += sizeof(stackval);
996
997 /* fixme: alignment */
998 DEBUG (printf ("arg_pos %d --> ", arg_pos));
999 if (sig->pinvoke)
1000 arg_pos += mono_type_native_stack_size (sig->params [i], &align);
1001 else
1002 arg_pos += mono_type_stack_size (sig->params [i], &align);
1003
1004 DEBUG (printf ("%d\n", stackval_arg_pos));
1005 }
1006
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);
1018 }
1019 }
1020
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);
1029
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);
1037 } else {
1038 enum_retvalue:
1039 switch (sig->ret->type) {
1040 case MONO_TYPE_VOID:
1041 break;
1042 case MONO_TYPE_BOOLEAN:
1043 case MONO_TYPE_U1:
1044 s390_lghi(p, s390_r2, 0);
1045 s390_ic (p, s390_r2, 0, s390_r10, 0);
1046 break;
1047 case MONO_TYPE_I2:
1048 case MONO_TYPE_U2:
1049 s390_lh (p, s390_r2, 0,s390_r10, 0);
1050 break;
1051 case MONO_TYPE_I4:
1052 case MONO_TYPE_U4:
1053 case MONO_TYPE_I:
1054 case MONO_TYPE_U:
1055 s390_lgf(p, s390_r2, 0, s390_r10, 0);
1056 break;
1057 case MONO_TYPE_OBJECT:
1058 case MONO_TYPE_STRING:
1059 case MONO_TYPE_CLASS:
1060 case MONO_TYPE_I8:
1061 s390_lg (p, s390_r2, 0, s390_r10, 0);
1062 break;
1063 case MONO_TYPE_R4:
1064 s390_le (p, s390_f0, 0, s390_r10, 0);
1065 break;
1066 case MONO_TYPE_R8:
1067 s390_ld (p, s390_f0, 0, s390_r10, 0);
1068 break;
1069 case MONO_TYPE_VALUETYPE:
1070 if (sig->ret->data.klass->enumtype) {
1071 simpletype = sig->ret->data.klass->enum_basetype->type;
1072 goto enum_retvalue;
1073 }
1074 /*---------------------------------*/
1075 /* Call stackval_to_data to return */
1076 /* the structure */
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)));
1084 if (sz.retStruct) {
1085 /*------------------------------------------*/
1086 /* Get stackval_to_data to set result area */
1087 /*------------------------------------------*/
1088 s390_lgr (p, s390_r4, s390_r8);
1089 } else {
1090 /*------------------------------------------*/
1091 /* Give stackval_to_data a temp result area */
1092 /*------------------------------------------*/
1093 s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos);
1094 }
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);
1098 switch (retSize) {
1099 case 0:
1100 break;
1101 case 1:
1102 s390_lghi(p, s390_r2, 0);
1103 s390_ic (p, s390_r2, 0, s390_r10, 0);
1104 break;
1105 case 2:
1106 s390_lh (p, s390_r2, 0, s390_r10, 0);
1107 break;
1108 case 4:
1109 s390_lgf(p, s390_r2, 0, s390_r10, 0);
1110 break;
1111 case 8:
1112 s390_lg (p, s390_r2, 0, s390_r10, 0);
1113 break;
1114 default: ;
1115 /*-------------------------------------------------*/
1116 /* stackval_to_data has placed data in result area */
1117 /*-------------------------------------------------*/
1118 }
1119 break;
1120 default:
1121 g_error ("Type 0x%x not handled yet in thunk creation",
1122 sig->ret->type);
1123 break;
1124 }
1125 }
1126
1127 /*----------------------------------------------------------*/
1128 /* epilog */
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);
1134
1135 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
1136
1137 DEBUG (printf ("Delegate [end emiting]\n"));
1138
1139 ji = g_new0 (MonoJitInfo, 1);
1140 ji->method = method;
1141 ji->code_size = p - code_buffer;
1142 ji->code_start = code_buffer;
1143
1144 mono_jit_info_table_add (mono_get_root_domain (), ji);
1145
1146 return ji->code_start;
1147 }
1148
1149 /*========================= End of Function ========================*/
1150