This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] libffi structure passing for AIX/Darwin
- From: Andreas Tobler <toa at pop dot agri dot ch>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: David Edelsohn <dje at watson dot ibm dot com>, Geoff Keating <geoffk at geoffk dot org>
- Date: Thu, 18 Sep 2003 19:47:20 +0200
- Subject: [patch] libffi structure passing for AIX/Darwin
Hi,
This is the rework of the previously posted patch for darwin.
The patch implements the structure passing for closures and ffi_call.
It now works for AIX as well. Tested on Darwin and AIX.
Ok for mainline?
Thanks,
Andreas
P.S, if the ChangeLog entry is looking ugly (formatting), then it is
only because of copy&paste. In the file itself it is looking fine.
2003-09-18 Andreas Tobler <a.tobler@schweiz.ch>
David Edelsohn <edelsohn@gnu.org>
* src/types.c (double): Add AIX and Darwin to the right TYPEDEF.
* src/powerpc/aix_closure.S: Remove the pointer to the outgoing
parameter stack.
* src/powerpc/darwin_closure.S: Likewise.
* src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures
according to the Darwin/AIX ABI.
(ffi_prep_cif_machdep): Likewise.
(ffi_closure_helper_DARWIN): Likewise.
Remove the outgoing parameter stack logic. Simplify the
evaluation of the different CASE types.
(ffi_prep_clousure): Avoid the casts on lvalues. Change the
branch statement in the trampoline code.
Index: src/types.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/types.c,v
retrieving revision 1.9
diff -c -r1.9 types.c
*** src/types.c 11 Sep 2003 05:17:56 -0000 1.9
--- src/types.c 18 Sep 2003 17:34:20 -0000
***************
*** 76,82 ****
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
! #elif defined ARM || defined SH || defined POWERPC64
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
--- 76,82 ----
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
! #elif defined ARM || defined SH || defined POWERPC64 || defined POWERPC_AIX || defined POWERPC_DARWIN
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
Index: src/powerpc/aix_closure.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/aix_closure.S,v
retrieving revision 1.2
diff -c -r1.2 aix_closure.S
*** src/powerpc/aix_closure.S 7 Feb 2003 04:31:20 -0000 1.2
--- src/powerpc/aix_closure.S 18 Sep 2003 17:34:20 -0000
***************
*** 105,112 ****
/* 24 Bytes (Linkage Area) */
/* 32 Bytes (params) */
! /* 104 Bytes (13*8 from FPR) */
! /* 8 Bytes (result)
/* 168 Bytes */
stwu r1,-176(r1) /* skip over caller save area
--- 105,112 ----
/* 24 Bytes (Linkage Area) */
/* 32 Bytes (params) */
! /* 104 Bytes (13*8 from FPR) */
! /* 8 Bytes (result) */
/* 168 Bytes */
stwu r1,-176(r1) /* skip over caller save area
***************
*** 144,163 ****
/* set up registers for the routine that actually does the work */
/* get the context pointer from the trampoline */
mr r3,r11
!
/* now load up the pointer to the result storage */
addi r4,r1,160
!
/* now load up the pointer to the saved gpr registers */
addi r5,r1,200
/* now load up the pointer to the saved fpr registers */
addi r6,r1,56
- /* now load up the pointer to the outgoing parameter */
- /* stack in the previous frame */
- addi r7,r1,232
-
/* make the call */
bl .ffi_closure_helper_DARWIN
nop
--- 144,159 ----
/* set up registers for the routine that actually does the work */
/* get the context pointer from the trampoline */
mr r3,r11
!
/* now load up the pointer to the result storage */
addi r4,r1,160
!
/* now load up the pointer to the saved gpr registers */
addi r5,r1,200
/* now load up the pointer to the saved fpr registers */
addi r6,r1,56
/* make the call */
bl .ffi_closure_helper_DARWIN
nop
Index: src/powerpc/darwin_closure.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/darwin_closure.S,v
retrieving revision 1.4
diff -c -r1.4 darwin_closure.S
*** src/powerpc/darwin_closure.S 10 Mar 2003 19:10:26 -0000 1.4
--- src/powerpc/darwin_closure.S 18 Sep 2003 17:34:20 -0000
***************
*** 31,37 ****
.text
.align 2
.globl _ffi_closure_ASM
!
.text
.align 2
_ffi_closure_ASM:
--- 31,37 ----
.text
.align 2
.globl _ffi_closure_ASM
!
.text
.align 2
_ffi_closure_ASM:
***************
*** 44,56 ****
104 Bytes (13*8 from FPR)
8 Bytes (result)
168 Bytes */
!
stwu r1,-176(r1) /* skip over caller save area
keep stack aligned to 16 */
LCFI1:
/* we want to build up an area for the parameters passed
in registers (both floating point and integer) */
!
/* we store gpr 3 to gpr 10 (aligned to 4)
in the parents outgoing area */
stw r3, 200(r1)
--- 44,56 ----
104 Bytes (13*8 from FPR)
8 Bytes (result)
168 Bytes */
!
stwu r1,-176(r1) /* skip over caller save area
keep stack aligned to 16 */
LCFI1:
/* we want to build up an area for the parameters passed
in registers (both floating point and integer) */
!
/* we store gpr 3 to gpr 10 (aligned to 4)
in the parents outgoing area */
stw r3, 200(r1)
***************
*** 80,102 ****
/* set up registers for the routine that actually does the work */
/* get the context pointer from the trampoline */
mr r3,r11
!
/* now load up the pointer to the result storage */
addi r4,r1,160
!
/* now load up the pointer to the saved gpr registers */
addi r5,r1,200
/* now load up the pointer to the saved fpr registers */
addi r6,r1,56
- /* now load up the pointer to the outgoing parameter
- stack in the previous frame */
- addi r7,r1,232
-
/* make the call */
bl Lffi_closure_helper_DARWIN$stub
!
/* now r3 contains the return type */
/* so use it to look up in a table */
/* so we know how to deal with each type */
--- 80,98 ----
/* set up registers for the routine that actually does the work */
/* get the context pointer from the trampoline */
mr r3,r11
!
/* now load up the pointer to the result storage */
addi r4,r1,160
!
/* now load up the pointer to the saved gpr registers */
addi r5,r1,200
/* now load up the pointer to the saved fpr registers */
addi r6,r1,56
/* make the call */
bl Lffi_closure_helper_DARWIN$stub
!
/* now r3 contains the return type */
/* so use it to look up in a table */
/* so we know how to deal with each type */
***************
*** 114,120 ****
/* Each of the ret_typeX code fragments has to be exactly 16 bytes long */
/* (4 instructions). For cache effectiveness we align to a 16 byte boundary */
/* first. */
!
.align 4
nop
--- 110,116 ----
/* Each of the ret_typeX code fragments has to be exactly 16 bytes long */
/* (4 instructions). For cache effectiveness we align to a 16 byte boundary */
/* first. */
!
.align 4
nop
***************
*** 234,240 ****
lwz r0,8(r1) /* get return address */
mtlr r0 /* reset link register */
blr
!
/* END(ffi_closure_ASM) */
.data
--- 230,236 ----
lwz r0,8(r1) /* get return address */
mtlr r0 /* reset link register */
blr
!
/* END(ffi_closure_ASM) */
.data
Index: src/powerpc/ffi_darwin.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/ffi_darwin.c,v
retrieving revision 1.7
diff -c -r1.7 ffi_darwin.c
*** src/powerpc/ffi_darwin.c 7 Feb 2003 04:31:20 -0000 1.7
--- src/powerpc/ffi_darwin.c 18 Sep 2003 17:34:20 -0000
***************
*** 29,35 ****
#include <ffi_common.h>
#include <stdlib.h>
!
extern void ffi_closure_ASM(void);
enum {
--- 29,35 ----
#include <ffi_common.h>
#include <stdlib.h>
!
extern void ffi_closure_ASM(void);
enum {
***************
*** 81,88 ****
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/*@=exportheader@*/
{
! const unsigned bytes = ecif->cif->bytes;
! const unsigned flags = ecif->cif->flags;
/* 'stacktop' points at the previous backchain pointer. */
unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
--- 81,87 ----
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/*@=exportheader@*/
{
! const unsigned flags = ecif->cif->flags;
/* 'stacktop' points at the previous backchain pointer. */
unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
***************
*** 96,107 ****
/* 'next_arg' grows up as we put parameters in it. */
unsigned *next_arg = stack + 6; // 6 reserved posistions.
! int i=ecif->cif->nargs;
double double_tmp;
- float float_tmp;
void **p_argv = ecif->avalue;
unsigned gprvalue;
ffi_type** ptr = ecif->cif->arg_types;
/* Check that everything starts aligned properly. */
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
--- 95,107 ----
/* 'next_arg' grows up as we put parameters in it. */
unsigned *next_arg = stack + 6; // 6 reserved posistions.
! int i = ecif->cif->nargs;
double double_tmp;
void **p_argv = ecif->avalue;
unsigned gprvalue;
ffi_type** ptr = ecif->cif->arg_types;
+ char *dest_cpy;
+ unsigned size_al = 0;
/* Check that everything starts aligned properly. */
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
***************
*** 163,178 ****
gprvalue = *(signed short *)*p_argv;
goto putgpr;
! case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
! case FFI_TYPE_LONGDOUBLE:
#endif
!
! memcpy((char*)next_arg, (char *)*p_argv, (*ptr)->size);
! next_arg+=(((((*ptr)->size) + 3) & ~0x3)/4);
! break;
!
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
--- 163,191 ----
gprvalue = *(signed short *)*p_argv;
goto putgpr;
! case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
! case FFI_TYPE_LONGDOUBLE:
#endif
! dest_cpy = (char *) next_arg;
!
! /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
! SI 4 bytes) are aligned as if they were those modes.
! Structures with 3 byte in size are padded upwards. */
! size_al = (*ptr)->size;
! /* If the first member of the struct is a double, then align
! the struct to double-word.
! Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
! if ((*ptr)->elements[0]->type == 3)
! size_al = ALIGN((*ptr)->size, 8);
! if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
! dest_cpy += 4 - size_al;
!
! memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
! next_arg += (size_al + 3) / 4;
! break;
!
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
***************
*** 187,193 ****
}
/* Check that we didn't overrun the stack... */
- //FFI_ASSERT(copy_space >= (char *)next_arg);
//FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
//FFI_ASSERT((unsigned *)fpr_base
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
--- 200,205 ----
***************
*** 203,209 ****
unsigned bytes;
int fparg_count = 0, intarg_count = 0;
unsigned flags = 0;
! unsigned struct_copy_size = 0;
/* All the machine-independent calculation of cif->bytes will be wrong.
Redo the calculation for DARWIN. */
--- 215,221 ----
unsigned bytes;
int fparg_count = 0, intarg_count = 0;
unsigned flags = 0;
! unsigned size_al = 0;
/* All the machine-independent calculation of cif->bytes will be wrong.
Redo the calculation for DARWIN. */
***************
*** 281,287 ****
on the stack. If they go on the stack, they must
be 8-byte-aligned. */
if (intarg_count == NUM_GPR_ARG_REGISTERS-1
! || intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)
intarg_count++;
intarg_count += 2;
break;
--- 293,299 ----
on the stack. If they go on the stack, they must
be 8-byte-aligned. */
if (intarg_count == NUM_GPR_ARG_REGISTERS-1
! || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0))
intarg_count++;
intarg_count += 2;
break;
***************
*** 290,296 ****
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
#endif
! intarg_count+=(((*ptr)->size + 3) & ~0x3)/4;
break;
default:
--- 302,314 ----
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
#endif
! size_al = (*ptr)->size;
! /* If the first member of the struct is a double, then align
! the struct to double-word.
! Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
! if ((*ptr)->elements[0]->type == 3)
! size_al = ALIGN((*ptr)->size, 8);
! intarg_count += (size_al + 3) / 4;
break;
default:
***************
*** 303,311 ****
if (fparg_count != 0)
flags |= FLAG_FP_ARGUMENTS;
! if (struct_copy_size != 0)
! flags |= FLAG_ARG_NEEDS_COPY;
!
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
--- 321,327 ----
if (fparg_count != 0)
flags |= FLAG_FP_ARGUMENTS;
!
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
***************
*** 321,327 ****
cif->flags = flags;
cif->bytes = bytes;
!
return FFI_OK;
}
--- 337,343 ----
cif->flags = flags;
cif->bytes = bytes;
!
return FFI_OK;
}
***************
*** 349,355 ****
ecif.cif = cif;
ecif.avalue = avalue;
!
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
--- 365,371 ----
ecif.cif = cif;
ecif.avalue = avalue;
!
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
***************
*** 362,368 ****
}
else
ecif.rvalue = rvalue;
!
switch (cif->abi)
{
case FFI_AIX:
--- 378,384 ----
}
else
ecif.rvalue = rvalue;
!
switch (cif->abi)
{
case FFI_AIX:
***************
*** 385,391 ****
static void flush_icache(char *);
static void flush_range(char *, int);
!
/* The layout of a function descriptor. A C function pointer really */
/* points to one of these. */
--- 401,407 ----
static void flush_icache(char *);
static void flush_range(char *, int);
!
/* The layout of a function descriptor. A C function pointer really */
/* points to one of these. */
***************
*** 397,403 ****
/* here I'd like to add the stack frame layout we use in darwin_closure.S
* and aix_clsoure.S
*
! /* SP previous -> +---------------------------------------+ <--- child frame
| back chain to caller 4 |
+---------------------------------------+ 4
| saved CR 4 |
--- 413,419 ----
/* here I'd like to add the stack frame layout we use in darwin_closure.S
* and aix_clsoure.S
*
! * SP previous -> +---------------------------------------+ <--- child frame
| back chain to caller 4 |
+---------------------------------------+ 4
| saved CR 4 |
***************
*** 441,447 ****
| . |
| r10 |
+---------------------------------------+ 232
! | PST area, overflow part |
+---------------------------------------+ xxx
| ???? |
+---------------------------------------+ xxx
--- 457,463 ----
| . |
| r10 |
+---------------------------------------+ 232
! | overflow part |
+---------------------------------------+ xxx
| ???? |
+---------------------------------------+ xxx
***************
*** 456,462 ****
unsigned int *tramp;
struct ffi_aix_trampoline_struct *tramp_aix;
aix_fd *fd;
!
switch (cif->abi)
{
case FFI_DARWIN:
--- 472,478 ----
unsigned int *tramp;
struct ffi_aix_trampoline_struct *tramp_aix;
aix_fd *fd;
!
switch (cif->abi)
{
case FFI_DARWIN:
***************
*** 464,487 ****
FFI_ASSERT (cif->abi == FFI_DARWIN);
tramp = (unsigned int *) &closure->tramp[0];
! tramp[0] = 0x7c0802a6; /* mflr r0 */
! tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
! tramp[4] = 0x7d6802a6; /* mflr r11 */
! tramp[5] = 0x818b0000; /* lwz r12,0(r11) /* function address */
! tramp[6] = 0x7c0803a6; /* mtlr r0 */
! tramp[7] = 0x7d8903a6; /* mtctr r12 */
! tramp[8] = 0x816b0004; /* lwz r11,4(r11) /* static chain */
! tramp[9] = 0x4e800420; /* bctr */
! *(void **) &tramp[2] = (void *)ffi_closure_ASM; /* function */
! *(void **) &tramp[3] = (void *)closure; /* context */
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
! /* Flush the icache. Only necessary on Darwin */
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
!
break;
case FFI_AIX:
--- 480,503 ----
FFI_ASSERT (cif->abi == FFI_DARWIN);
tramp = (unsigned int *) &closure->tramp[0];
! tramp[0] = 0x7c0802a6; /* mflr r0 */
! tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
! tramp[4] = 0x7d6802a6; /* mflr r11 */
! tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
! tramp[6] = 0x7c0803a6; /* mtlr r0 */
! tramp[7] = 0x7d8903a6; /* mtctr r12 */
! tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
! tramp[9] = 0x4e800420; /* bctr */
! tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
! tramp[3] = (unsigned long) closure; /* context */
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
! /* Flush the icache. Only necessary on Darwin. */
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
!
break;
case FFI_AIX:
***************
*** 530,537 ****
flush_icache(addr1+size-1);
}
! int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*,
! unsigned long*, unsigned long*);
/* Basically the trampoline invokes ffi_closure_ASM, and on
* entry, r11 holds the address of the closure.
--- 546,559 ----
flush_icache(addr1+size-1);
}
! typedef union
! {
! float f;
! double d;
! } ffi_dblfl;
!
! int ffi_closure_helper_DARWIN (ffi_closure*, void*,
! unsigned long*, ffi_dblfl*);
/* Basically the trampoline invokes ffi_closure_ASM, and on
* entry, r11 holds the address of the closure.
***************
*** 541,555 ****
* following helper function to do most of the work
*/
! int
! ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
! unsigned long * pgr, unsigned long * pfr,
! unsigned long * pst)
{
! /* rvalue is the pointer to space for return value in closure assembly */
! /* pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM */
! /* pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM */
! /* pst is the pointer to outgoing parameter stack in original caller */
void ** avalue;
ffi_type ** arg_types;
--- 563,575 ----
* following helper function to do most of the work
*/
! int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
! unsigned long * pgr, ffi_dblfl * pfr)
{
! /* rvalue is the pointer to space for return value in closure assembly
! pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
! pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
!
void ** avalue;
ffi_type ** arg_types;
***************
*** 558,563 ****
--- 578,584 ----
long ng; /* number of general registers already used */
ffi_cif * cif;
double temp;
+ unsigned size_al;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
***************
*** 569,577 ****
returns the data directly to the caller. */
if (cif->rtype->type == FFI_TYPE_STRUCT)
{
! rvalue = (void *)pgr;
! ng++;
pgr++;
}
i = 0;
--- 590,598 ----
returns the data directly to the caller. */
if (cif->rtype->type == FFI_TYPE_STRUCT)
{
! rvalue = (void *) *pgr;
pgr++;
+ ng++;
}
i = 0;
***************
*** 582,706 ****
while (i < avn)
{
switch (arg_types[i]->type)
! {
! case FFI_TYPE_SINT8:
! case FFI_TYPE_UINT8:
! /* there are 8 gpr registers used to pass values */
! if (ng < 8) {
! avalue[i] = (((char *)pgr)+3);
! ng++;
! pgr++;
! } else {
! avalue[i] = (((char *)pst)+3);
! pst++;
! }
! break;
!
! case FFI_TYPE_SINT16:
! case FFI_TYPE_UINT16:
! /* there are 8 gpr registers used to pass values */
! if (ng < 8) {
! avalue[i] = (((char *)pgr)+2);
! ng++;
! pgr++;
! } else {
! avalue[i] = (((char *)pst)+2);
! pst++;
! }
! break;
!
! case FFI_TYPE_SINT32:
! case FFI_TYPE_UINT32:
! case FFI_TYPE_POINTER:
! case FFI_TYPE_STRUCT:
! /* there are 8 gpr registers used to pass values */
! if (ng < 8) {
! avalue[i] = pgr;
! ng++;
! pgr++;
! } else {
! avalue[i] = pst;
! pst++;
! }
! break;
!
! case FFI_TYPE_SINT64:
! case FFI_TYPE_UINT64:
! /* long long ints are passed in two gpr's if available or in
! * the pst, one place is a bit odd, when a long long passes
! * the boundary between gpr and pst area we have to increment
! * the pst by one.
! */
! if (ng < 7) {
! avalue[i] = pgr;
! ng+=2;
! pgr+=2;
! } else if (ng == 7) {
! avalue[i] = pgr;
! ng++;
! pgr++;
! pst++;
! } else {
! avalue[i] = pst;
! pst+=2;
! }
! break;
!
! case FFI_TYPE_FLOAT:
! /* a float value consumes a GPR
! *
! * there are 13 64bit floating point registers
*/
!
! if ((ng > 7) && (nf < 13)) {
! pst++;
! }
! if (nf < 13) {
! temp = *(double*)pfr;
! *(float*)pfr = (float)temp;
! avalue[i] = pfr;
! nf++;
! pfr+=2;
! ng++;
! pgr++;
!
! } else {
! avalue[i] = pst;
! nf++;
! pst++;
! }
! break;
! case FFI_TYPE_DOUBLE:
/* a double value consumes two GPRs
! *
! * there are 13 64bit floating point registers
*/
!
! if ((ng == 7) && (nf < 13)) {
! pst++; /* if only one gpr is left the double steals it */
! } else if ((ng > 7) && (nf < 13)) {
! pst+=2; /* a double consumes two GPRs in Darwin/AIX */
! }
! if (nf < 13) {
! avalue[i] = pfr;
! nf++;
! pfr+=2;
! ng+=2;
! pgr+=2;
!
! } else {
! avalue[i] = pst;
! nf++;
! pst+=2;
! }
! break;
default:
FFI_ASSERT(0);
-
}
-
i++;
}
--- 603,699 ----
while (i < avn)
{
switch (arg_types[i]->type)
! {
! case FFI_TYPE_SINT8:
! case FFI_TYPE_UINT8:
! avalue[i] = (char *) pgr + 3;
! ng++;
! pgr++;
! break;
!
! case FFI_TYPE_SINT16:
! case FFI_TYPE_UINT16:
! avalue[i] = (char *) pgr + 2;
! ng++;
! pgr++;
! break;
!
! case FFI_TYPE_SINT32:
! case FFI_TYPE_UINT32:
! case FFI_TYPE_POINTER:
! avalue[i] = pgr;
! ng++;
! pgr++;
! break;
!
! case FFI_TYPE_STRUCT:
! /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
! SI 4 bytes) are aligned as if they were those modes. */
! size_al = arg_types[i]->size;
! /* If the first member of the struct is a double, then align
! the struct to double-word.
! Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
! if (arg_types[i]->elements[0]->type == 3)
! size_al = ALIGN(arg_types[i]->size, 8);
! if (size_al < 3 && cif->abi == FFI_DARWIN)
! avalue[i] = (void*) pgr + 4 - size_al;
! else
! avalue[i] = (void*) pgr;
! ng += (size_al + 3) / 4;
! pgr += (size_al + 3) / 4;
! break;
!
! case FFI_TYPE_SINT64:
! case FFI_TYPE_UINT64:
! /* Long long ints are passed in two gpr's. */
! avalue[i] = pgr;
! ng += 2;
! pgr += 2;
! break;
!
! case FFI_TYPE_FLOAT:
! /* a float value consumes a GPR
! *
! * here are 13 64bit floating point registers.
*/
! if (nf < NUM_FPR_ARG_REGISTERS)
! {
! temp = pfr->d;
! pfr->f = (float)temp;
! avalue[i] = pfr;
! pfr++;
! }
! else
! {
! avalue[i] = pgr;
! }
! nf++;
! ng++;
! pgr++;
! break;
! case FFI_TYPE_DOUBLE:
/* a double value consumes two GPRs
! *
! * There are 13 64bit floating point registers.
*/
! if (nf < NUM_FPR_ARG_REGISTERS)
! {
! avalue[i] = pfr;
! pfr++;
! }
! else
! {
! avalue[i] = pgr;
! }
! nf++;
! ng += 2;
! pgr += 2;
! break;
default:
FFI_ASSERT(0);
}
i++;
}
***************
*** 708,712 ****
/* Tell ffi_closure_ASM to perform return type promotions. */
return cif->rtype->type;
-
}
--- 701,704 ----