2018-08-29 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libffi / src / x86 / ffi64.c
blob131b5e3d14864130b7eef16896fadf07680617b3
1 /* -----------------------------------------------------------------------
2 ffi64.c - Copyright (c) 2013 The Written Word, Inc.
3 Copyright (c) 2011 Anthony Green
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 "internal64.h"
38 #ifdef __x86_64__
40 #define MAX_GPR_REGS 6
41 #define MAX_SSE_REGS 8
43 #if defined(__INTEL_COMPILER)
44 #include "xmmintrin.h"
45 #define UINT128 __m128
46 #else
47 #if defined(__SUNPRO_C)
48 #include <sunmedia_types.h>
49 #define UINT128 __m128i
50 #else
51 #define UINT128 __int128_t
52 #endif
53 #endif
55 union big_int_union
57 UINT32 i32;
58 UINT64 i64;
59 UINT128 i128;
62 struct register_args
64 /* Registers for argument passing. */
65 UINT64 gpr[MAX_GPR_REGS];
66 union big_int_union sse[MAX_SSE_REGS];
67 UINT64 rax; /* ssecount */
68 UINT64 r10; /* static chain */
71 extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
72 void *raddr, void (*fnaddr)(void)) FFI_HIDDEN;
74 /* All reference to register classes here is identical to the code in
75 gcc/config/i386/i386.c. Do *not* change one without the other. */
77 /* Register class used for passing given 64bit part of the argument.
78 These represent classes as documented by the PS ABI, with the
79 exception of SSESF, SSEDF classes, that are basically SSE class,
80 just gcc will use SF or DFmode move instead of DImode to avoid
81 reformatting penalties.
83 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
84 whenever possible (upper half does contain padding). */
85 enum x86_64_reg_class
87 X86_64_NO_CLASS,
88 X86_64_INTEGER_CLASS,
89 X86_64_INTEGERSI_CLASS,
90 X86_64_SSE_CLASS,
91 X86_64_SSESF_CLASS,
92 X86_64_SSEDF_CLASS,
93 X86_64_SSEUP_CLASS,
94 X86_64_X87_CLASS,
95 X86_64_X87UP_CLASS,
96 X86_64_COMPLEX_X87_CLASS,
97 X86_64_MEMORY_CLASS
100 #define MAX_CLASSES 4
102 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
104 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
105 of this code is to classify each 8bytes of incoming argument by the register
106 class and assign registers accordingly. */
108 /* Return the union class of CLASS1 and CLASS2.
109 See the x86-64 PS ABI for details. */
111 static enum x86_64_reg_class
112 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
114 /* Rule #1: If both classes are equal, this is the resulting class. */
115 if (class1 == class2)
116 return class1;
118 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
119 the other class. */
120 if (class1 == X86_64_NO_CLASS)
121 return class2;
122 if (class2 == X86_64_NO_CLASS)
123 return class1;
125 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
126 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
127 return X86_64_MEMORY_CLASS;
129 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
130 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
131 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
132 return X86_64_INTEGERSI_CLASS;
133 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
134 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
135 return X86_64_INTEGER_CLASS;
137 /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
138 MEMORY is used. */
139 if (class1 == X86_64_X87_CLASS
140 || class1 == X86_64_X87UP_CLASS
141 || class1 == X86_64_COMPLEX_X87_CLASS
142 || class2 == X86_64_X87_CLASS
143 || class2 == X86_64_X87UP_CLASS
144 || class2 == X86_64_COMPLEX_X87_CLASS)
145 return X86_64_MEMORY_CLASS;
147 /* Rule #6: Otherwise class SSE is used. */
148 return X86_64_SSE_CLASS;
151 /* Classify the argument of type TYPE and mode MODE.
152 CLASSES will be filled by the register class used to pass each word
153 of the operand. The number of words is returned. In case the parameter
154 should be passed in memory, 0 is returned. As a special case for zero
155 sized containers, classes[0] will be NO_CLASS and 1 is returned.
157 See the x86-64 PS ABI for details.
159 static size_t
160 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
161 size_t byte_offset)
163 switch (type->type)
165 case FFI_TYPE_UINT8:
166 case FFI_TYPE_SINT8:
167 case FFI_TYPE_UINT16:
168 case FFI_TYPE_SINT16:
169 case FFI_TYPE_UINT32:
170 case FFI_TYPE_SINT32:
171 case FFI_TYPE_UINT64:
172 case FFI_TYPE_SINT64:
173 case FFI_TYPE_POINTER:
174 do_integer:
176 size_t size = byte_offset + type->size;
178 if (size <= 4)
180 classes[0] = X86_64_INTEGERSI_CLASS;
181 return 1;
183 else if (size <= 8)
185 classes[0] = X86_64_INTEGER_CLASS;
186 return 1;
188 else if (size <= 12)
190 classes[0] = X86_64_INTEGER_CLASS;
191 classes[1] = X86_64_INTEGERSI_CLASS;
192 return 2;
194 else if (size <= 16)
196 classes[0] = classes[1] = X86_64_INTEGER_CLASS;
197 return 2;
199 else
200 FFI_ASSERT (0);
202 case FFI_TYPE_FLOAT:
203 if (!(byte_offset % 8))
204 classes[0] = X86_64_SSESF_CLASS;
205 else
206 classes[0] = X86_64_SSE_CLASS;
207 return 1;
208 case FFI_TYPE_DOUBLE:
209 classes[0] = X86_64_SSEDF_CLASS;
210 return 1;
211 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
212 case FFI_TYPE_LONGDOUBLE:
213 classes[0] = X86_64_X87_CLASS;
214 classes[1] = X86_64_X87UP_CLASS;
215 return 2;
216 #endif
217 case FFI_TYPE_STRUCT:
219 const size_t UNITS_PER_WORD = 8;
220 size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
221 ffi_type **ptr;
222 int i;
223 enum x86_64_reg_class subclasses[MAX_CLASSES];
225 /* If the struct is larger than 32 bytes, pass it on the stack. */
226 if (type->size > 32)
227 return 0;
229 for (i = 0; i < words; i++)
230 classes[i] = X86_64_NO_CLASS;
232 /* Zero sized arrays or structures are NO_CLASS. We return 0 to
233 signalize memory class, so handle it as special case. */
234 if (!words)
236 case FFI_TYPE_VOID:
237 classes[0] = X86_64_NO_CLASS;
238 return 1;
241 /* Merge the fields of structure. */
242 for (ptr = type->elements; *ptr != NULL; ptr++)
244 size_t num;
246 byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
248 num = classify_argument (*ptr, subclasses, byte_offset % 8);
249 if (num == 0)
250 return 0;
251 for (i = 0; i < num; i++)
253 size_t pos = byte_offset / 8;
254 classes[i + pos] =
255 merge_classes (subclasses[i], classes[i + pos]);
258 byte_offset += (*ptr)->size;
261 if (words > 2)
263 /* When size > 16 bytes, if the first one isn't
264 X86_64_SSE_CLASS or any other ones aren't
265 X86_64_SSEUP_CLASS, everything should be passed in
266 memory. */
267 if (classes[0] != X86_64_SSE_CLASS)
268 return 0;
270 for (i = 1; i < words; i++)
271 if (classes[i] != X86_64_SSEUP_CLASS)
272 return 0;
275 /* Final merger cleanup. */
276 for (i = 0; i < words; i++)
278 /* If one class is MEMORY, everything should be passed in
279 memory. */
280 if (classes[i] == X86_64_MEMORY_CLASS)
281 return 0;
283 /* The X86_64_SSEUP_CLASS should be always preceded by
284 X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
285 if (classes[i] == X86_64_SSEUP_CLASS
286 && classes[i - 1] != X86_64_SSE_CLASS
287 && classes[i - 1] != X86_64_SSEUP_CLASS)
289 /* The first one should never be X86_64_SSEUP_CLASS. */
290 FFI_ASSERT (i != 0);
291 classes[i] = X86_64_SSE_CLASS;
294 /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
295 everything should be passed in memory. */
296 if (classes[i] == X86_64_X87UP_CLASS
297 && (classes[i - 1] != X86_64_X87_CLASS))
299 /* The first one should never be X86_64_X87UP_CLASS. */
300 FFI_ASSERT (i != 0);
301 return 0;
304 return words;
306 case FFI_TYPE_COMPLEX:
308 ffi_type *inner = type->elements[0];
309 switch (inner->type)
311 case FFI_TYPE_INT:
312 case FFI_TYPE_UINT8:
313 case FFI_TYPE_SINT8:
314 case FFI_TYPE_UINT16:
315 case FFI_TYPE_SINT16:
316 case FFI_TYPE_UINT32:
317 case FFI_TYPE_SINT32:
318 case FFI_TYPE_UINT64:
319 case FFI_TYPE_SINT64:
320 goto do_integer;
322 case FFI_TYPE_FLOAT:
323 classes[0] = X86_64_SSE_CLASS;
324 if (byte_offset % 8)
326 classes[1] = X86_64_SSESF_CLASS;
327 return 2;
329 return 1;
330 case FFI_TYPE_DOUBLE:
331 classes[0] = classes[1] = X86_64_SSEDF_CLASS;
332 return 2;
333 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
334 case FFI_TYPE_LONGDOUBLE:
335 classes[0] = X86_64_COMPLEX_X87_CLASS;
336 return 1;
337 #endif
341 abort();
344 /* Examine the argument and return set number of register required in each
345 class. Return zero iff parameter should be passed in memory, otherwise
346 the number of registers. */
348 static size_t
349 examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
350 _Bool in_return, int *pngpr, int *pnsse)
352 size_t n;
353 int i, ngpr, nsse;
355 n = classify_argument (type, classes, 0);
356 if (n == 0)
357 return 0;
359 ngpr = nsse = 0;
360 for (i = 0; i < n; ++i)
361 switch (classes[i])
363 case X86_64_INTEGER_CLASS:
364 case X86_64_INTEGERSI_CLASS:
365 ngpr++;
366 break;
367 case X86_64_SSE_CLASS:
368 case X86_64_SSESF_CLASS:
369 case X86_64_SSEDF_CLASS:
370 nsse++;
371 break;
372 case X86_64_NO_CLASS:
373 case X86_64_SSEUP_CLASS:
374 break;
375 case X86_64_X87_CLASS:
376 case X86_64_X87UP_CLASS:
377 case X86_64_COMPLEX_X87_CLASS:
378 return in_return != 0;
379 default:
380 abort ();
383 *pngpr = ngpr;
384 *pnsse = nsse;
386 return n;
389 /* Perform machine dependent cif processing. */
391 ffi_status
392 ffi_prep_cif_machdep (ffi_cif *cif)
394 int gprcount, ssecount, i, avn, ngpr, nsse, flags;
395 enum x86_64_reg_class classes[MAX_CLASSES];
396 size_t bytes, n, rtype_size;
397 ffi_type *rtype;
399 if (cif->abi != FFI_UNIX64)
400 return FFI_BAD_ABI;
402 gprcount = ssecount = 0;
404 rtype = cif->rtype;
405 rtype_size = rtype->size;
406 switch (rtype->type)
408 case FFI_TYPE_VOID:
409 flags = UNIX64_RET_VOID;
410 break;
411 case FFI_TYPE_UINT8:
412 flags = UNIX64_RET_UINT8;
413 break;
414 case FFI_TYPE_SINT8:
415 flags = UNIX64_RET_SINT8;
416 break;
417 case FFI_TYPE_UINT16:
418 flags = UNIX64_RET_UINT16;
419 break;
420 case FFI_TYPE_SINT16:
421 flags = UNIX64_RET_SINT16;
422 break;
423 case FFI_TYPE_UINT32:
424 flags = UNIX64_RET_UINT32;
425 break;
426 case FFI_TYPE_INT:
427 case FFI_TYPE_SINT32:
428 flags = UNIX64_RET_SINT32;
429 break;
430 case FFI_TYPE_UINT64:
431 case FFI_TYPE_SINT64:
432 flags = UNIX64_RET_INT64;
433 break;
434 case FFI_TYPE_POINTER:
435 flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
436 break;
437 case FFI_TYPE_FLOAT:
438 flags = UNIX64_RET_XMM32;
439 break;
440 case FFI_TYPE_DOUBLE:
441 flags = UNIX64_RET_XMM64;
442 break;
443 case FFI_TYPE_LONGDOUBLE:
444 flags = UNIX64_RET_X87;
445 break;
446 case FFI_TYPE_STRUCT:
447 n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
448 if (n == 0)
450 /* The return value is passed in memory. A pointer to that
451 memory is the first argument. Allocate a register for it. */
452 gprcount++;
453 /* We don't have to do anything in asm for the return. */
454 flags = UNIX64_RET_VOID | UNIX64_FLAG_RET_IN_MEM;
456 else
458 _Bool sse0 = SSE_CLASS_P (classes[0]);
460 if (rtype_size == 4 && sse0)
461 flags = UNIX64_RET_XMM32;
462 else if (rtype_size == 8)
463 flags = sse0 ? UNIX64_RET_XMM64 : UNIX64_RET_INT64;
464 else
466 _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
467 if (sse0 && sse1)
468 flags = UNIX64_RET_ST_XMM0_XMM1;
469 else if (sse0)
470 flags = UNIX64_RET_ST_XMM0_RAX;
471 else if (sse1)
472 flags = UNIX64_RET_ST_RAX_XMM0;
473 else
474 flags = UNIX64_RET_ST_RAX_RDX;
475 flags |= rtype_size << UNIX64_SIZE_SHIFT;
478 break;
479 case FFI_TYPE_COMPLEX:
480 switch (rtype->elements[0]->type)
482 case FFI_TYPE_UINT8:
483 case FFI_TYPE_SINT8:
484 case FFI_TYPE_UINT16:
485 case FFI_TYPE_SINT16:
486 case FFI_TYPE_INT:
487 case FFI_TYPE_UINT32:
488 case FFI_TYPE_SINT32:
489 case FFI_TYPE_UINT64:
490 case FFI_TYPE_SINT64:
491 flags = UNIX64_RET_ST_RAX_RDX | (rtype_size << UNIX64_SIZE_SHIFT);
492 break;
493 case FFI_TYPE_FLOAT:
494 flags = UNIX64_RET_XMM64;
495 break;
496 case FFI_TYPE_DOUBLE:
497 flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT);
498 break;
499 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
500 case FFI_TYPE_LONGDOUBLE:
501 flags = UNIX64_RET_X87_2;
502 break;
503 #endif
504 default:
505 return FFI_BAD_TYPEDEF;
507 break;
508 default:
509 return FFI_BAD_TYPEDEF;
512 /* Go over all arguments and determine the way they should be passed.
513 If it's in a register and there is space for it, let that be so. If
514 not, add it's size to the stack byte count. */
515 for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
517 if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
518 || gprcount + ngpr > MAX_GPR_REGS
519 || ssecount + nsse > MAX_SSE_REGS)
521 long align = cif->arg_types[i]->alignment;
523 if (align < 8)
524 align = 8;
526 bytes = ALIGN (bytes, align);
527 bytes += cif->arg_types[i]->size;
529 else
531 gprcount += ngpr;
532 ssecount += nsse;
535 if (ssecount)
536 flags |= UNIX64_FLAG_XMM_ARGS;
538 cif->flags = flags;
539 cif->bytes = ALIGN (bytes, 8);
541 return FFI_OK;
544 static void
545 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
546 void **avalue, void *closure)
548 enum x86_64_reg_class classes[MAX_CLASSES];
549 char *stack, *argp;
550 ffi_type **arg_types;
551 int gprcount, ssecount, ngpr, nsse, i, avn, flags;
552 struct register_args *reg_args;
554 /* Can't call 32-bit mode from 64-bit mode. */
555 FFI_ASSERT (cif->abi == FFI_UNIX64);
557 /* If the return value is a struct and we don't have a return value
558 address then we need to make one. Otherwise we can ignore it. */
559 flags = cif->flags;
560 if (rvalue == NULL)
562 if (flags & UNIX64_FLAG_RET_IN_MEM)
563 rvalue = alloca (cif->rtype->size);
564 else
565 flags = UNIX64_RET_VOID;
568 /* Allocate the space for the arguments, plus 4 words of temp space. */
569 stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
570 reg_args = (struct register_args *) stack;
571 argp = stack + sizeof (struct register_args);
573 reg_args->r10 = (uintptr_t) closure;
575 gprcount = ssecount = 0;
577 /* If the return value is passed in memory, add the pointer as the
578 first integer argument. */
579 if (flags & UNIX64_FLAG_RET_IN_MEM)
580 reg_args->gpr[gprcount++] = (unsigned long) rvalue;
582 avn = cif->nargs;
583 arg_types = cif->arg_types;
585 for (i = 0; i < avn; ++i)
587 size_t n, size = arg_types[i]->size;
589 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
590 if (n == 0
591 || gprcount + ngpr > MAX_GPR_REGS
592 || ssecount + nsse > MAX_SSE_REGS)
594 long align = arg_types[i]->alignment;
596 /* Stack arguments are *always* at least 8 byte aligned. */
597 if (align < 8)
598 align = 8;
600 /* Pass this argument in memory. */
601 argp = (void *) ALIGN (argp, align);
602 memcpy (argp, avalue[i], size);
603 argp += size;
605 else
607 /* The argument is passed entirely in registers. */
608 char *a = (char *) avalue[i];
609 int j;
611 for (j = 0; j < n; j++, a += 8, size -= 8)
613 switch (classes[j])
615 case X86_64_NO_CLASS:
616 case X86_64_SSEUP_CLASS:
617 break;
618 case X86_64_INTEGER_CLASS:
619 case X86_64_INTEGERSI_CLASS:
620 /* Sign-extend integer arguments passed in general
621 purpose registers, to cope with the fact that
622 LLVM incorrectly assumes that this will be done
623 (the x86-64 PS ABI does not specify this). */
624 switch (arg_types[i]->type)
626 case FFI_TYPE_SINT8:
627 reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
628 break;
629 case FFI_TYPE_SINT16:
630 reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
631 break;
632 case FFI_TYPE_SINT32:
633 reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
634 break;
635 default:
636 reg_args->gpr[gprcount] = 0;
637 memcpy (&reg_args->gpr[gprcount], a, size);
639 gprcount++;
640 break;
641 case X86_64_SSE_CLASS:
642 case X86_64_SSEDF_CLASS:
643 reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
644 break;
645 case X86_64_SSESF_CLASS:
646 reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
647 break;
648 default:
649 abort();
654 reg_args->rax = ssecount;
656 ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
657 flags, rvalue, fn);
660 void
661 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
663 ffi_call_int (cif, fn, rvalue, avalue, NULL);
666 void
667 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
668 void **avalue, void *closure)
670 ffi_call_int (cif, fn, rvalue, avalue, closure);
673 extern void ffi_closure_unix64(void) FFI_HIDDEN;
674 extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
676 ffi_status
677 ffi_prep_closure_loc (ffi_closure* closure,
678 ffi_cif* cif,
679 void (*fun)(ffi_cif*, void*, void**, void*),
680 void *user_data,
681 void *codeloc)
683 static const unsigned char trampoline[16] = {
684 /* leaq -0x7(%rip),%r10 # 0x0 */
685 0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
686 /* jmpq *0x3(%rip) # 0x10 */
687 0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
688 /* nopl (%rax) */
689 0x0f, 0x1f, 0x00
691 void (*dest)(void);
692 char *tramp = closure->tramp;
694 if (cif->abi != FFI_UNIX64)
695 return FFI_BAD_ABI;
697 if (cif->flags & UNIX64_FLAG_XMM_ARGS)
698 dest = ffi_closure_unix64_sse;
699 else
700 dest = ffi_closure_unix64;
702 memcpy (tramp, trampoline, sizeof(trampoline));
703 *(UINT64 *)(tramp + 16) = (uintptr_t)dest;
705 closure->cif = cif;
706 closure->fun = fun;
707 closure->user_data = user_data;
709 return FFI_OK;
712 int FFI_HIDDEN
713 ffi_closure_unix64_inner(ffi_cif *cif,
714 void (*fun)(ffi_cif*, void*, void**, void*),
715 void *user_data,
716 void *rvalue,
717 struct register_args *reg_args,
718 char *argp)
720 void **avalue;
721 ffi_type **arg_types;
722 long i, avn;
723 int gprcount, ssecount, ngpr, nsse;
724 int flags;
726 avn = cif->nargs;
727 flags = cif->flags;
728 avalue = alloca(avn * sizeof(void *));
729 gprcount = ssecount = 0;
731 if (flags & UNIX64_FLAG_RET_IN_MEM)
733 /* On return, %rax will contain the address that was passed
734 by the caller in %rdi. */
735 void *r = (void *)(uintptr_t)reg_args->gpr[gprcount++];
736 *(void **)rvalue = r;
737 rvalue = r;
738 flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
741 arg_types = cif->arg_types;
742 for (i = 0; i < avn; ++i)
744 enum x86_64_reg_class classes[MAX_CLASSES];
745 size_t n;
747 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
748 if (n == 0
749 || gprcount + ngpr > MAX_GPR_REGS
750 || ssecount + nsse > MAX_SSE_REGS)
752 long align = arg_types[i]->alignment;
754 /* Stack arguments are *always* at least 8 byte aligned. */
755 if (align < 8)
756 align = 8;
758 /* Pass this argument in memory. */
759 argp = (void *) ALIGN (argp, align);
760 avalue[i] = argp;
761 argp += arg_types[i]->size;
763 /* If the argument is in a single register, or two consecutive
764 integer registers, then we can use that address directly. */
765 else if (n == 1
766 || (n == 2 && !(SSE_CLASS_P (classes[0])
767 || SSE_CLASS_P (classes[1]))))
769 /* The argument is in a single register. */
770 if (SSE_CLASS_P (classes[0]))
772 avalue[i] = &reg_args->sse[ssecount];
773 ssecount += n;
775 else
777 avalue[i] = &reg_args->gpr[gprcount];
778 gprcount += n;
781 /* Otherwise, allocate space to make them consecutive. */
782 else
784 char *a = alloca (16);
785 int j;
787 avalue[i] = a;
788 for (j = 0; j < n; j++, a += 8)
790 if (SSE_CLASS_P (classes[j]))
791 memcpy (a, &reg_args->sse[ssecount++], 8);
792 else
793 memcpy (a, &reg_args->gpr[gprcount++], 8);
798 /* Invoke the closure. */
799 fun (cif, rvalue, avalue, user_data);
801 /* Tell assembly how to perform return type promotions. */
802 return flags;
805 extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
806 extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
808 ffi_status
809 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
810 void (*fun)(ffi_cif*, void*, void**, void*))
812 if (cif->abi != FFI_UNIX64)
813 return FFI_BAD_ABI;
815 closure->tramp = (cif->flags & UNIX64_FLAG_XMM_ARGS
816 ? ffi_go_closure_unix64_sse
817 : ffi_go_closure_unix64);
818 closure->cif = cif;
819 closure->fun = fun;
821 return FFI_OK;
824 #endif /* __x86_64__ */