[PATCH v2 2/3] RISC-V: setmem for RISCV with V extension
[official-gcc.git] / libffi / src / x86 / ffi64.c
blob438b374e2fbbf89bc97deefe7a2085f2a06c6661
1 /* -----------------------------------------------------------------------
2 ffi64.c - Copyright (c) 2011, 2018 Anthony Green
3 Copyright (c) 2013 The Written Word, Inc.
4 Copyright (c) 2008, 2010 Red Hat, Inc.
5 Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
7 x86-64 Foreign Function Interface
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 ``Software''), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 ----------------------------------------------------------------------- */
30 #include <ffi.h>
31 #include <ffi_common.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdint.h>
36 #include <tramp.h>
37 #include "internal64.h"
39 #ifdef __x86_64__
41 #define MAX_GPR_REGS 6
42 #define MAX_SSE_REGS 8
44 #if defined(__INTEL_COMPILER)
45 #include "xmmintrin.h"
46 #define UINT128 __m128
47 #else
48 #if defined(__SUNPRO_C)
49 #include <sunmedia_types.h>
50 #define UINT128 __m128i
51 #else
52 #define UINT128 __int128_t
53 #endif
54 #endif
56 union big_int_union
58 UINT32 i32;
59 UINT64 i64;
60 UINT128 i128;
63 struct register_args
65 /* Registers for argument passing. */
66 UINT64 gpr[MAX_GPR_REGS];
67 union big_int_union sse[MAX_SSE_REGS];
68 UINT64 rax; /* ssecount */
69 UINT64 r10; /* static chain */
72 extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
73 void *raddr, void (*fnaddr)(void)) FFI_HIDDEN;
75 /* All reference to register classes here is identical to the code in
76 gcc/config/i386/i386.c. Do *not* change one without the other. */
78 /* Register class used for passing given 64bit part of the argument.
79 These represent classes as documented by the PS ABI, with the
80 exception of SSESF, SSEDF classes, that are basically SSE class,
81 just gcc will use SF or DFmode move instead of DImode to avoid
82 reformatting penalties.
84 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
85 whenever possible (upper half does contain padding). */
86 enum x86_64_reg_class
88 X86_64_NO_CLASS,
89 X86_64_INTEGER_CLASS,
90 X86_64_INTEGERSI_CLASS,
91 X86_64_SSE_CLASS,
92 X86_64_SSESF_CLASS,
93 X86_64_SSEDF_CLASS,
94 X86_64_SSEUP_CLASS,
95 X86_64_X87_CLASS,
96 X86_64_X87UP_CLASS,
97 X86_64_COMPLEX_X87_CLASS,
98 X86_64_MEMORY_CLASS
101 #define MAX_CLASSES 4
103 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
105 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
106 of this code is to classify each 8bytes of incoming argument by the register
107 class and assign registers accordingly. */
109 /* Return the union class of CLASS1 and CLASS2.
110 See the x86-64 PS ABI for details. */
112 static enum x86_64_reg_class
113 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
115 /* Rule #1: If both classes are equal, this is the resulting class. */
116 if (class1 == class2)
117 return class1;
119 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
120 the other class. */
121 if (class1 == X86_64_NO_CLASS)
122 return class2;
123 if (class2 == X86_64_NO_CLASS)
124 return class1;
126 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
127 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
128 return X86_64_MEMORY_CLASS;
130 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
131 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
132 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
133 return X86_64_INTEGERSI_CLASS;
134 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
135 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
136 return X86_64_INTEGER_CLASS;
138 /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
139 MEMORY is used. */
140 if (class1 == X86_64_X87_CLASS
141 || class1 == X86_64_X87UP_CLASS
142 || class1 == X86_64_COMPLEX_X87_CLASS
143 || class2 == X86_64_X87_CLASS
144 || class2 == X86_64_X87UP_CLASS
145 || class2 == X86_64_COMPLEX_X87_CLASS)
146 return X86_64_MEMORY_CLASS;
148 /* Rule #6: Otherwise class SSE is used. */
149 return X86_64_SSE_CLASS;
152 /* Classify the argument of type TYPE and mode MODE.
153 CLASSES will be filled by the register class used to pass each word
154 of the operand. The number of words is returned. In case the parameter
155 should be passed in memory, 0 is returned. As a special case for zero
156 sized containers, classes[0] will be NO_CLASS and 1 is returned.
158 See the x86-64 PS ABI for details.
160 static size_t
161 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
162 size_t byte_offset)
164 switch (type->type)
166 case FFI_TYPE_UINT8:
167 case FFI_TYPE_SINT8:
168 case FFI_TYPE_UINT16:
169 case FFI_TYPE_SINT16:
170 case FFI_TYPE_UINT32:
171 case FFI_TYPE_SINT32:
172 case FFI_TYPE_UINT64:
173 case FFI_TYPE_SINT64:
174 case FFI_TYPE_POINTER:
175 do_integer:
177 size_t size = byte_offset + type->size;
179 if (size <= 4)
181 classes[0] = X86_64_INTEGERSI_CLASS;
182 return 1;
184 else if (size <= 8)
186 classes[0] = X86_64_INTEGER_CLASS;
187 return 1;
189 else if (size <= 12)
191 classes[0] = X86_64_INTEGER_CLASS;
192 classes[1] = X86_64_INTEGERSI_CLASS;
193 return 2;
195 else if (size <= 16)
197 classes[0] = classes[1] = X86_64_INTEGER_CLASS;
198 return 2;
200 else
201 FFI_ASSERT (0);
203 case FFI_TYPE_FLOAT:
204 if (!(byte_offset % 8))
205 classes[0] = X86_64_SSESF_CLASS;
206 else
207 classes[0] = X86_64_SSE_CLASS;
208 return 1;
209 case FFI_TYPE_DOUBLE:
210 classes[0] = X86_64_SSEDF_CLASS;
211 return 1;
212 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
213 case FFI_TYPE_LONGDOUBLE:
214 classes[0] = X86_64_X87_CLASS;
215 classes[1] = X86_64_X87UP_CLASS;
216 return 2;
217 #endif
218 case FFI_TYPE_STRUCT:
220 const size_t UNITS_PER_WORD = 8;
221 size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1)
222 / UNITS_PER_WORD;
223 ffi_type **ptr;
224 unsigned int i;
225 enum x86_64_reg_class subclasses[MAX_CLASSES];
227 /* If the struct is larger than 32 bytes, pass it on the stack. */
228 if (type->size > 32)
229 return 0;
231 for (i = 0; i < words; i++)
232 classes[i] = X86_64_NO_CLASS;
234 /* Zero sized arrays or structures are NO_CLASS. We return 0 to
235 signalize memory class, so handle it as special case. */
236 if (!words)
238 case FFI_TYPE_VOID:
239 classes[0] = X86_64_NO_CLASS;
240 return 1;
243 /* Merge the fields of structure. */
244 for (ptr = type->elements; *ptr != NULL; ptr++)
246 size_t num, pos;
248 byte_offset = FFI_ALIGN (byte_offset, (*ptr)->alignment);
250 num = classify_argument (*ptr, subclasses, byte_offset % 8);
251 if (num == 0)
252 return 0;
253 pos = byte_offset / 8;
254 for (i = 0; i < num && (i + pos) < words; i++)
256 size_t pos = byte_offset / 8;
257 classes[i + pos] =
258 merge_classes (subclasses[i], classes[i + pos]);
261 byte_offset += (*ptr)->size;
264 if (words > 2)
266 /* When size > 16 bytes, if the first one isn't
267 X86_64_SSE_CLASS or any other ones aren't
268 X86_64_SSEUP_CLASS, everything should be passed in
269 memory. */
270 if (classes[0] != X86_64_SSE_CLASS)
271 return 0;
273 for (i = 1; i < words; i++)
274 if (classes[i] != X86_64_SSEUP_CLASS)
275 return 0;
278 /* Final merger cleanup. */
279 for (i = 0; i < words; i++)
281 /* If one class is MEMORY, everything should be passed in
282 memory. */
283 if (classes[i] == X86_64_MEMORY_CLASS)
284 return 0;
286 /* The X86_64_SSEUP_CLASS should be always preceded by
287 X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
288 if (i > 1 && classes[i] == X86_64_SSEUP_CLASS
289 && classes[i - 1] != X86_64_SSE_CLASS
290 && classes[i - 1] != X86_64_SSEUP_CLASS)
292 /* The first one should never be X86_64_SSEUP_CLASS. */
293 FFI_ASSERT (i != 0);
294 classes[i] = X86_64_SSE_CLASS;
297 /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
298 everything should be passed in memory. */
299 if (i > 1 && classes[i] == X86_64_X87UP_CLASS
300 && (classes[i - 1] != X86_64_X87_CLASS))
302 /* The first one should never be X86_64_X87UP_CLASS. */
303 FFI_ASSERT (i != 0);
304 return 0;
307 return words;
309 case FFI_TYPE_COMPLEX:
311 ffi_type *inner = type->elements[0];
312 switch (inner->type)
314 case FFI_TYPE_INT:
315 case FFI_TYPE_UINT8:
316 case FFI_TYPE_SINT8:
317 case FFI_TYPE_UINT16:
318 case FFI_TYPE_SINT16:
319 case FFI_TYPE_UINT32:
320 case FFI_TYPE_SINT32:
321 case FFI_TYPE_UINT64:
322 case FFI_TYPE_SINT64:
323 goto do_integer;
325 case FFI_TYPE_FLOAT:
326 classes[0] = X86_64_SSE_CLASS;
327 if (byte_offset % 8)
329 classes[1] = X86_64_SSESF_CLASS;
330 return 2;
332 return 1;
333 case FFI_TYPE_DOUBLE:
334 classes[0] = classes[1] = X86_64_SSEDF_CLASS;
335 return 2;
336 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
337 case FFI_TYPE_LONGDOUBLE:
338 classes[0] = X86_64_COMPLEX_X87_CLASS;
339 return 1;
340 #endif
344 abort();
347 /* Examine the argument and return set number of register required in each
348 class. Return zero iff parameter should be passed in memory, otherwise
349 the number of registers. */
351 static size_t
352 examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
353 _Bool in_return, int *pngpr, int *pnsse)
355 size_t n;
356 unsigned int i;
357 int ngpr, nsse;
359 n = classify_argument (type, classes, 0);
360 if (n == 0)
361 return 0;
363 ngpr = nsse = 0;
364 for (i = 0; i < n; ++i)
365 switch (classes[i])
367 case X86_64_INTEGER_CLASS:
368 case X86_64_INTEGERSI_CLASS:
369 ngpr++;
370 break;
371 case X86_64_SSE_CLASS:
372 case X86_64_SSESF_CLASS:
373 case X86_64_SSEDF_CLASS:
374 nsse++;
375 break;
376 case X86_64_NO_CLASS:
377 case X86_64_SSEUP_CLASS:
378 break;
379 case X86_64_X87_CLASS:
380 case X86_64_X87UP_CLASS:
381 case X86_64_COMPLEX_X87_CLASS:
382 return in_return != 0;
383 default:
384 abort ();
387 *pngpr = ngpr;
388 *pnsse = nsse;
390 return n;
393 /* Perform machine dependent cif processing. */
395 #ifndef __ILP32__
396 extern ffi_status
397 ffi_prep_cif_machdep_efi64(ffi_cif *cif);
398 #endif
400 ffi_status FFI_HIDDEN
401 ffi_prep_cif_machdep (ffi_cif *cif)
403 int gprcount, ssecount, i, avn, ngpr, nsse;
404 unsigned flags;
405 enum x86_64_reg_class classes[MAX_CLASSES];
406 size_t bytes, n, rtype_size;
407 ffi_type *rtype;
409 #ifndef __ILP32__
410 if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64)
411 return ffi_prep_cif_machdep_efi64(cif);
412 #endif
413 if (cif->abi != FFI_UNIX64)
414 return FFI_BAD_ABI;
416 gprcount = ssecount = 0;
418 rtype = cif->rtype;
419 rtype_size = rtype->size;
420 switch (rtype->type)
422 case FFI_TYPE_VOID:
423 flags = UNIX64_RET_VOID;
424 break;
425 case FFI_TYPE_UINT8:
426 flags = UNIX64_RET_UINT8;
427 break;
428 case FFI_TYPE_SINT8:
429 flags = UNIX64_RET_SINT8;
430 break;
431 case FFI_TYPE_UINT16:
432 flags = UNIX64_RET_UINT16;
433 break;
434 case FFI_TYPE_SINT16:
435 flags = UNIX64_RET_SINT16;
436 break;
437 case FFI_TYPE_UINT32:
438 flags = UNIX64_RET_UINT32;
439 break;
440 case FFI_TYPE_INT:
441 case FFI_TYPE_SINT32:
442 flags = UNIX64_RET_SINT32;
443 break;
444 case FFI_TYPE_UINT64:
445 case FFI_TYPE_SINT64:
446 flags = UNIX64_RET_INT64;
447 break;
448 case FFI_TYPE_POINTER:
449 flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
450 break;
451 case FFI_TYPE_FLOAT:
452 flags = UNIX64_RET_XMM32;
453 break;
454 case FFI_TYPE_DOUBLE:
455 flags = UNIX64_RET_XMM64;
456 break;
457 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
458 case FFI_TYPE_LONGDOUBLE:
459 flags = UNIX64_RET_X87;
460 break;
461 #endif
462 case FFI_TYPE_STRUCT:
463 n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
464 if (n == 0)
466 /* The return value is passed in memory. A pointer to that
467 memory is the first argument. Allocate a register for it. */
468 gprcount++;
469 /* We don't have to do anything in asm for the return. */
470 flags = UNIX64_RET_VOID | UNIX64_FLAG_RET_IN_MEM;
472 else
474 _Bool sse0 = SSE_CLASS_P (classes[0]);
476 if (rtype_size == 4 && sse0)
477 flags = UNIX64_RET_XMM32;
478 else if (rtype_size == 8)
479 flags = sse0 ? UNIX64_RET_XMM64 : UNIX64_RET_INT64;
480 else
482 _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
483 if (sse0 && sse1)
484 flags = UNIX64_RET_ST_XMM0_XMM1;
485 else if (sse0)
486 flags = UNIX64_RET_ST_XMM0_RAX;
487 else if (sse1)
488 flags = UNIX64_RET_ST_RAX_XMM0;
489 else
490 flags = UNIX64_RET_ST_RAX_RDX;
491 flags |= rtype_size << UNIX64_SIZE_SHIFT;
494 break;
495 case FFI_TYPE_COMPLEX:
496 switch (rtype->elements[0]->type)
498 case FFI_TYPE_UINT8:
499 case FFI_TYPE_SINT8:
500 case FFI_TYPE_UINT16:
501 case FFI_TYPE_SINT16:
502 case FFI_TYPE_INT:
503 case FFI_TYPE_UINT32:
504 case FFI_TYPE_SINT32:
505 case FFI_TYPE_UINT64:
506 case FFI_TYPE_SINT64:
507 flags = UNIX64_RET_ST_RAX_RDX | ((unsigned) rtype_size << UNIX64_SIZE_SHIFT);
508 break;
509 case FFI_TYPE_FLOAT:
510 flags = UNIX64_RET_XMM64;
511 break;
512 case FFI_TYPE_DOUBLE:
513 flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT);
514 break;
515 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
516 case FFI_TYPE_LONGDOUBLE:
517 flags = UNIX64_RET_X87_2;
518 break;
519 #endif
520 default:
521 return FFI_BAD_TYPEDEF;
523 break;
524 default:
525 return FFI_BAD_TYPEDEF;
528 /* Go over all arguments and determine the way they should be passed.
529 If it's in a register and there is space for it, let that be so. If
530 not, add it's size to the stack byte count. */
531 for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
533 if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
534 || gprcount + ngpr > MAX_GPR_REGS
535 || ssecount + nsse > MAX_SSE_REGS)
537 long align = cif->arg_types[i]->alignment;
539 if (align < 8)
540 align = 8;
542 bytes = FFI_ALIGN (bytes, align);
543 bytes += cif->arg_types[i]->size;
545 else
547 gprcount += ngpr;
548 ssecount += nsse;
551 if (ssecount)
552 flags |= UNIX64_FLAG_XMM_ARGS;
554 cif->flags = flags;
555 cif->bytes = (unsigned) FFI_ALIGN (bytes, 8);
557 return FFI_OK;
560 static void
561 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
562 void **avalue, void *closure)
564 enum x86_64_reg_class classes[MAX_CLASSES];
565 char *stack, *argp;
566 ffi_type **arg_types;
567 int gprcount, ssecount, ngpr, nsse, i, avn, flags;
568 struct register_args *reg_args;
570 /* Can't call 32-bit mode from 64-bit mode. */
571 FFI_ASSERT (cif->abi == FFI_UNIX64);
573 /* If the return value is a struct and we don't have a return value
574 address then we need to make one. Otherwise we can ignore it. */
575 flags = cif->flags;
576 if (rvalue == NULL)
578 if (flags & UNIX64_FLAG_RET_IN_MEM)
579 rvalue = alloca (cif->rtype->size);
580 else
581 flags = UNIX64_RET_VOID;
584 /* Allocate the space for the arguments, plus 4 words of temp space. */
585 stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
586 reg_args = (struct register_args *) stack;
587 argp = stack + sizeof (struct register_args);
589 reg_args->r10 = (uintptr_t) closure;
591 gprcount = ssecount = 0;
593 /* If the return value is passed in memory, add the pointer as the
594 first integer argument. */
595 if (flags & UNIX64_FLAG_RET_IN_MEM)
596 reg_args->gpr[gprcount++] = (unsigned long) rvalue;
598 avn = cif->nargs;
599 arg_types = cif->arg_types;
601 for (i = 0; i < avn; ++i)
603 size_t n, size = arg_types[i]->size;
605 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
606 if (n == 0
607 || gprcount + ngpr > MAX_GPR_REGS
608 || ssecount + nsse > MAX_SSE_REGS)
610 long align = arg_types[i]->alignment;
612 /* Stack arguments are *always* at least 8 byte aligned. */
613 if (align < 8)
614 align = 8;
616 /* Pass this argument in memory. */
617 argp = (void *) FFI_ALIGN (argp, align);
618 memcpy (argp, avalue[i], size);
619 argp += size;
621 else
623 /* The argument is passed entirely in registers. */
624 char *a = (char *) avalue[i];
625 unsigned int j;
627 for (j = 0; j < n; j++, a += 8, size -= 8)
629 switch (classes[j])
631 case X86_64_NO_CLASS:
632 case X86_64_SSEUP_CLASS:
633 break;
634 case X86_64_INTEGER_CLASS:
635 case X86_64_INTEGERSI_CLASS:
636 /* Sign-extend integer arguments passed in general
637 purpose registers, to cope with the fact that
638 LLVM incorrectly assumes that this will be done
639 (the x86-64 PS ABI does not specify this). */
640 switch (arg_types[i]->type)
642 case FFI_TYPE_SINT8:
643 reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
644 break;
645 case FFI_TYPE_SINT16:
646 reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
647 break;
648 case FFI_TYPE_SINT32:
649 reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
650 break;
651 default:
652 reg_args->gpr[gprcount] = 0;
653 memcpy (&reg_args->gpr[gprcount], a, size);
655 gprcount++;
656 break;
657 case X86_64_SSE_CLASS:
658 case X86_64_SSEDF_CLASS:
659 memcpy (&reg_args->sse[ssecount++].i64, a, sizeof(UINT64));
660 break;
661 case X86_64_SSESF_CLASS:
662 memcpy (&reg_args->sse[ssecount++].i32, a, sizeof(UINT32));
663 break;
664 default:
665 abort();
670 reg_args->rax = ssecount;
672 ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
673 flags, rvalue, fn);
676 #ifndef __ILP32__
677 extern void
678 ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
679 #endif
681 void
682 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
684 #ifndef __ILP32__
685 if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64)
687 ffi_call_efi64(cif, fn, rvalue, avalue);
688 return;
690 #endif
691 ffi_call_int (cif, fn, rvalue, avalue, NULL);
694 #ifdef FFI_GO_CLOSURES
696 #ifndef __ILP32__
697 extern void
698 ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue,
699 void **avalue, void *closure);
700 #endif
702 void
703 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
704 void **avalue, void *closure)
706 #ifndef __ILP32__
707 if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64)
709 ffi_call_go_efi64(cif, fn, rvalue, avalue, closure);
710 return;
712 #endif
713 ffi_call_int (cif, fn, rvalue, avalue, closure);
716 #endif /* FFI_GO_CLOSURES */
718 extern void ffi_closure_unix64(void) FFI_HIDDEN;
719 extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
720 #if defined(FFI_EXEC_STATIC_TRAMP)
721 extern void ffi_closure_unix64_alt(void) FFI_HIDDEN;
722 extern void ffi_closure_unix64_sse_alt(void) FFI_HIDDEN;
723 #endif
725 #ifndef __ILP32__
726 extern ffi_status
727 ffi_prep_closure_loc_efi64(ffi_closure* closure,
728 ffi_cif* cif,
729 void (*fun)(ffi_cif*, void*, void**, void*),
730 void *user_data,
731 void *codeloc);
732 #endif
734 ffi_status
735 ffi_prep_closure_loc (ffi_closure* closure,
736 ffi_cif* cif,
737 void (*fun)(ffi_cif*, void*, void**, void*),
738 void *user_data,
739 void *codeloc)
741 static const unsigned char trampoline[24] = {
742 /* endbr64 */
743 0xf3, 0x0f, 0x1e, 0xfa,
744 /* leaq -0xb(%rip),%r10 # 0x0 */
745 0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff,
746 /* jmpq *0x7(%rip) # 0x18 */
747 0xff, 0x25, 0x07, 0x00, 0x00, 0x00,
748 /* nopl 0(%rax) */
749 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00
751 void (*dest)(void);
752 char *tramp = closure->tramp;
754 #ifndef __ILP32__
755 if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64)
756 return ffi_prep_closure_loc_efi64(closure, cif, fun, user_data, codeloc);
757 #endif
758 if (cif->abi != FFI_UNIX64)
759 return FFI_BAD_ABI;
761 if (cif->flags & UNIX64_FLAG_XMM_ARGS)
762 dest = ffi_closure_unix64_sse;
763 else
764 dest = ffi_closure_unix64;
766 #if defined(FFI_EXEC_STATIC_TRAMP)
767 if (ffi_tramp_is_present(closure))
769 /* Initialize the static trampoline's parameters. */
770 if (dest == ffi_closure_unix64_sse)
771 dest = ffi_closure_unix64_sse_alt;
772 else
773 dest = ffi_closure_unix64_alt;
774 ffi_tramp_set_parms (closure->ftramp, dest, closure);
775 goto out;
777 #endif
779 /* Initialize the dynamic trampoline. */
780 memcpy (tramp, trampoline, sizeof(trampoline));
781 *(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)dest;
783 out:
784 closure->cif = cif;
785 closure->fun = fun;
786 closure->user_data = user_data;
788 return FFI_OK;
791 int FFI_HIDDEN
792 ffi_closure_unix64_inner(ffi_cif *cif,
793 void (*fun)(ffi_cif*, void*, void**, void*),
794 void *user_data,
795 void *rvalue,
796 struct register_args *reg_args,
797 char *argp)
799 void **avalue;
800 ffi_type **arg_types;
801 long i, avn;
802 int gprcount, ssecount, ngpr, nsse;
803 int flags;
805 avn = cif->nargs;
806 flags = cif->flags;
807 avalue = alloca(avn * sizeof(void *));
808 gprcount = ssecount = 0;
810 if (flags & UNIX64_FLAG_RET_IN_MEM)
812 /* On return, %rax will contain the address that was passed
813 by the caller in %rdi. */
814 void *r = (void *)(uintptr_t)reg_args->gpr[gprcount++];
815 *(void **)rvalue = r;
816 rvalue = r;
817 flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
820 arg_types = cif->arg_types;
821 for (i = 0; i < avn; ++i)
823 enum x86_64_reg_class classes[MAX_CLASSES];
824 size_t n;
826 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
827 if (n == 0
828 || gprcount + ngpr > MAX_GPR_REGS
829 || ssecount + nsse > MAX_SSE_REGS)
831 long align = arg_types[i]->alignment;
833 /* Stack arguments are *always* at least 8 byte aligned. */
834 if (align < 8)
835 align = 8;
837 /* Pass this argument in memory. */
838 argp = (void *) FFI_ALIGN (argp, align);
839 avalue[i] = argp;
840 argp += arg_types[i]->size;
842 /* If the argument is in a single register, or two consecutive
843 integer registers, then we can use that address directly. */
844 else if (n == 1
845 || (n == 2 && !(SSE_CLASS_P (classes[0])
846 || SSE_CLASS_P (classes[1]))))
848 /* The argument is in a single register. */
849 if (SSE_CLASS_P (classes[0]))
851 avalue[i] = &reg_args->sse[ssecount];
852 ssecount += n;
854 else
856 avalue[i] = &reg_args->gpr[gprcount];
857 gprcount += n;
860 /* Otherwise, allocate space to make them consecutive. */
861 else
863 char *a = alloca (16);
864 unsigned int j;
866 avalue[i] = a;
867 for (j = 0; j < n; j++, a += 8)
869 if (SSE_CLASS_P (classes[j]))
870 memcpy (a, &reg_args->sse[ssecount++], 8);
871 else
872 memcpy (a, &reg_args->gpr[gprcount++], 8);
877 /* Invoke the closure. */
878 fun (cif, rvalue, avalue, user_data);
880 /* Tell assembly how to perform return type promotions. */
881 return flags;
884 #ifdef FFI_GO_CLOSURES
886 extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
887 extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
889 #ifndef __ILP32__
890 extern ffi_status
891 ffi_prep_go_closure_efi64(ffi_go_closure* closure, ffi_cif* cif,
892 void (*fun)(ffi_cif*, void*, void**, void*));
893 #endif
895 ffi_status
896 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
897 void (*fun)(ffi_cif*, void*, void**, void*))
899 #ifndef __ILP32__
900 if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64)
901 return ffi_prep_go_closure_efi64(closure, cif, fun);
902 #endif
903 if (cif->abi != FFI_UNIX64)
904 return FFI_BAD_ABI;
906 closure->tramp = (cif->flags & UNIX64_FLAG_XMM_ARGS
907 ? ffi_go_closure_unix64_sse
908 : ffi_go_closure_unix64);
909 closure->cif = cif;
910 closure->fun = fun;
912 return FFI_OK;
915 #endif /* FFI_GO_CLOSURES */
917 #if defined(FFI_EXEC_STATIC_TRAMP)
918 void *
919 ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
921 extern void *trampoline_code_table;
923 *map_size = UNIX64_TRAMP_MAP_SIZE;
924 *tramp_size = UNIX64_TRAMP_SIZE;
925 return &trampoline_code_table;
927 #endif
929 #endif /* __x86_64__ */