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] x86_64 libffi fix


Hello,

there are two problems with libffi on x86_64 in 32 bit mode:
1) Sizes of types are taken as in 64 bit mode
2) The code for closures attempts to load values from registers
   in asm statements. This does not work, as gcc does not know about
   it and it reorganizes code so that these loads are not valid.

this patch fixes them. OK for mainline and 3.3 branch?

Zdenek

Changelog:
	* libffi/include/ffi.h.in: Define X86 instead of X86_64 in 32
	bit mode.
	(FFI_TRAMPOLINE_SIZE): Changed.
	* libffi/src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV):
	Receive closure and arguments pointers through parameters.
	(FFI_INIT_TRAMPOLINE): Send them there.

Index: include/ffi.h.in
===================================================================
RCS file: /cvs/gcc/gcc/libffi/include/ffi.h.in,v
retrieving revision 1.20.2.3
diff -c -3 -p -r1.20.2.3 ffi.h.in
*** include/ffi.h.in	31 Jan 2003 21:50:21 -0000	1.20.2.3
--- include/ffi.h.in	20 Mar 2003 13:00:13 -0000
*************** extern "C" {
*** 170,175 ****--- 170,182 ----
  #endif
  #endif
  
+ #ifdef X86_64
+ #if defined (__i386__)
+ #undef X86_64
+ #define X86
+ #endif
+ #endif
+ 
  #ifndef LIBFFI_ASM
  
  /* ---- Generic type definitions ----------------------------------------- */
*************** size_t ffi_java_raw_size (ffi_cif *cif);
*** 401,407 ****
  #ifdef __i386__
  
  #define FFI_CLOSURES 1		/* x86 supports closures */
! #define FFI_TRAMPOLINE_SIZE 10
  #define FFI_NATIVE_RAW_API 1	/* and has native raw api support */
  
  #elif defined(IA64)
--- 408,414 ----
  #ifdef __i386__
  
  #define FFI_CLOSURES 1		/* x86 supports closures */
! #define FFI_TRAMPOLINE_SIZE 15
  #define FFI_NATIVE_RAW_API 1	/* and has native raw api support */
  
  #elif defined(IA64)
Index: src/x86/ffi.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/x86/ffi.c,v
retrieving revision 1.8.12.1
diff -c -3 -p -r1.8.12.1 ffi.c
*** src/x86/ffi.c	7 Dec 2002 16:41:45 -0000	1.8.12.1
--- src/x86/ffi.c	20 Mar 2003 13:00:13 -0000
*************** void ffi_call(/* at dependent@*/ ffi_cif *c
*** 214,248 ****
  
  static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
  					 void** args, ffi_cif* cif);
! static void ffi_closure_SYSV ();
! static void ffi_closure_raw_SYSV ();
  
! /* This function is jumped to by the trampoline, on entry, %ecx (a
!  * caller-save register) holds the address of the closure.  
!  * Clearly, this requires __GNUC__, so perhaps we should translate this
!  * into an assembly file if this is to be distributed with ffi.
!  */
  
  static void
! ffi_closure_SYSV ()
  {
    // this is our return value storage
    long double    res;
  
    // our various things...
-   void          *args;
    ffi_cif       *cif;
    void         **arg_area;
-   ffi_closure   *closure;
    unsigned short rtype;
    void          *resp = (void*)&res;
  
-   /* grab the trampoline context pointer */
-   asm ("movl %%ecx,%0" : "=r" (closure));
-   
    cif         = closure->cif;
    arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
!   asm ("leal 8(%%ebp),%0" : "=q" (args));  
  
    /* this call will initialize ARG_AREA, such that each
     * element in that array points to the corresponding 
--- 214,241 ----
  
  static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
  					 void** args, ffi_cif* cif);
! static void ffi_closure_SYSV (ffi_closure *, void *);
! static void ffi_closure_raw_SYSV (ffi_raw_closure *, void *);
  
! /* This function is jumped to by the trampoline */
  
  static void
! ffi_closure_SYSV (closure, args)
!      ffi_closure *closure;
!      void *args;
  {
    // this is our return value storage
    long double    res;
  
    // our various things...
    ffi_cif       *cif;
    void         **arg_area;
    unsigned short rtype;
    void          *resp = (void*)&res;
  
    cif         = closure->cif;
    arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
!   args        += 4;
  
    /* this call will initialize ARG_AREA, such that each
     * element in that array points to the corresponding 
*************** ffi_prep_incoming_args_SYSV(char *stack,
*** 330,340 ****
  ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
     unsigned int  __fun = (unsigned int)(FUN); \
     unsigned int  __ctx = (unsigned int)(CTX); \
!    unsigned int  __dis = __fun - ((unsigned int) __tramp + 10); \
!    *(unsigned char*) &__tramp[0] = 0xb9; \
!    *(unsigned int*)  &__tramp[1] = __ctx; \
!    *(unsigned char*) &__tramp[5] = 0xe9; \
!    *(unsigned int*)  &__tramp[6] = __dis; \
   })
  
  
--- 323,338 ----
  ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
     unsigned int  __fun = (unsigned int)(FUN); \
     unsigned int  __ctx = (unsigned int)(CTX); \
!    unsigned int  __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE - 4); \
!    *(unsigned char*) &__tramp[0] = 0x54; /* pushl %esp */\
!    *(unsigned char*) &__tramp[1] = 0x68; \
!    *(unsigned int*)  &__tramp[2] = __ctx; /* pushl __ctx */ \
!    *(unsigned char *)  &__tramp[6] = 0xe8; \
!    *(unsigned int*)  &__tramp[7] = __dis; /* call __fun  */ \
!    *(unsigned char *)  &__tramp[11] = 0x83; \
!    *(unsigned char *)  &__tramp[12] = 0xc4; \
!    *(unsigned char *)  &__tramp[13] = 0x08; /* add $8, %esp */ \
!    *(unsigned char *)  &__tramp[14] = 0xc3; /* ret */ \
   })
  
  
*************** ffi_prep_closure (ffi_closure* closure,
*** 364,393 ****
  #if !FFI_NO_RAW_API
  
  static void
! ffi_closure_raw_SYSV ()
  {
    // this is our return value storage
    long double    res;
  
    // our various things...
-   void            *args;
    ffi_raw         *raw_args;
    ffi_cif         *cif;
-   ffi_raw_closure *closure;
    unsigned short   rtype;
    void            *resp = (void*)&res;
  
-   /* grab the trampoline context pointer */
-   asm ("movl %%ecx,%0" : "=r" (closure));
- 
-   /* take the argument pointer */
-   asm ("leal 8(%%ebp),%0" : "=q" (args));  
- 
    /* get the cif */
    cif = closure->cif;
  
    /* the SYSV/X86 abi matches the RAW API exactly, well.. almost */
!   raw_args = (ffi_raw*) args;
  
    (closure->fun) (cif, resp, raw_args, closure->user_data);
  
--- 362,385 ----
  #if !FFI_NO_RAW_API
  
  static void
! ffi_closure_raw_SYSV (closure, args)
!      ffi_raw_closure *closure;
!      void *args;
  {
    // this is our return value storage
    long double    res;
  
    // our various things...
    ffi_raw         *raw_args;
    ffi_cif         *cif;
    unsigned short   rtype;
    void            *resp = (void*)&res;
  
    /* get the cif */
    cif = closure->cif;
  
    /* the SYSV/X86 abi matches the RAW API exactly, well.. almost */
!   raw_args = (ffi_raw*) args + 4;
  
    (closure->fun) (cif, resp, raw_args, closure->user_data);
  


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