This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]