Libffi: closures for x86_64

Andrew Haley aph@redhat.com
Mon Jan 27 17:45:00 GMT 2003


This isn't complete -- it doesn't support passing structs or long
doubles -- but it's enough for Java.

Andrew.


2003-01-27  Andrew Haley  <aph@redhat.com>

        * include/ffi.h.in: Enable FFI_CLOSURES for x86_64.
        * src/x86/ffi64.c (ffi_prep_closure): New.
        (ffi_closure_UNIX64_inner): New.

Index: include/ffi.h.in
===================================================================
RCS file: /cvs/gcc/gcc/libffi/include/ffi.h.in,v
retrieving revision 1.22
diff -p -2 -c -r1.22 ffi.h.in
*** include/ffi.h.in	3 Jan 2003 23:08:55 -0000	1.22
--- include/ffi.h.in	27 Jan 2003 17:25:34 -0000
*************** struct ffi_ia64_trampoline_struct {
*** 472,475 ****
--- 472,481 ----
  #define FFI_NATIVE_RAW_API 0
  
+ #elif defined(__x86_64__)
+ 
+ #define FFI_CLOSURES 1
+ #define FFI_TRAMPOLINE_SIZE 24
+ #define FFI_NATIVE_RAW_API 0
+ 
  #else 
  
Index: src/x86/ffi64.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/x86/ffi64.c,v
retrieving revision 1.3
diff -p -2 -c -r1.3 ffi64.c
*** src/x86/ffi64.c	14 Jan 2003 18:42:28 -0000	1.3
--- src/x86/ffi64.c	27 Jan 2003 17:25:35 -0000
***************
*** 28,31 ****
--- 28,32 ----
  
  #include <stdlib.h>
+ #include <stdarg.h>
  
  /* ffi_prep_args is called by the assembly routine once stack space
*************** void ffi_call(/*@dependent@*/ ffi_cif *c
*** 572,574 ****
--- 573,706 ----
  }
  
+ extern void ffi_closure_UNIX64(void);
+ 
+ ffi_status
+ ffi_prep_closure (ffi_closure* closure,
+ 		  ffi_cif* cif,
+ 		  void (*fun)(ffi_cif*, void*, void**, void*),
+ 		  void *user_data)
+ {
+   unsigned short *tramp;
+ 
+   /* FFI_ASSERT (cif->abi == FFI_OSF);  */
+ 
+   tramp = (unsigned short *) &closure->tramp[0];
+   tramp[0] = 0xbb49;		/* mov <code>, %r11d	*/
+   tramp[5] = 0xba49;		/* mov <data>, %r10	*/
+   tramp[10] = 0xff49;		/* jmp *%r11	*/
+   tramp[11] = 0x00e3;
+   *(void **) &tramp[1] = ffi_closure_UNIX64;
+   *(void **) &tramp[6] = closure;
+ 
+   closure->cif = cif;
+   closure->fun = fun;
+   closure->user_data = user_data;
+ 
+   return FFI_OK;
+ }
+ 
+ int
+ ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp)
+ {
+   ffi_cif *cif;
+   void **avalue;
+   ffi_type **arg_types;
+   long i, avn, argn;
+ 
+   cif = closure->cif;
+   avalue = alloca(cif->nargs * sizeof(void *));
+ 
+   argn = 0;
+ 
+   i = 0;
+   avn = cif->nargs;
+   arg_types = cif->arg_types;
+   
+   /* Grab the addresses of the arguments from the stack frame.  */
+   while (i < avn)
+     {
+       switch (arg_types[i]->type)
+ 	{
+ 	case FFI_TYPE_SINT8:
+ 	case FFI_TYPE_UINT8:
+ 	case FFI_TYPE_SINT16:
+ 	case FFI_TYPE_UINT16:
+ 	case FFI_TYPE_SINT32:
+ 	case FFI_TYPE_UINT32:
+ 	case FFI_TYPE_SINT64:
+ 	case FFI_TYPE_UINT64:
+ 	case FFI_TYPE_POINTER:
+ 	  {
+ 	    if (l->gp_offset > 48-8)
+ 	      {
+ 		avalue[i] = l->overflow_arg_area;
+ 		l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
+ 	      }
+ 	    else
+ 	      {
+ 		avalue[i] = (char *)l->reg_save_area + l->gp_offset;
+ 		l->gp_offset += 8;
+ 	      }
+ 	  }
+ 	  break;
+ 
+ 	case FFI_TYPE_STRUCT:
+ 	  /* FIXME  */
+ 	  FFI_ASSERT(0);
+ 	  break;
+ 
+ 	case FFI_TYPE_DOUBLE:
+ 	  {
+ 	    if (l->fp_offset > 176-16)
+ 	      {
+ 		avalue[i] = l->overflow_arg_area;
+ 		l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
+ 	      }
+ 	    else
+ 	      {
+ 		avalue[i] = (char *)l->reg_save_area + l->fp_offset;
+ 		l->fp_offset += 16;
+ 	      }
+ 	  }
+ #if DEBUG_FFI
+ 	  fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);
+ #endif
+ 	  break;
+ 	  
+ 	case FFI_TYPE_FLOAT:
+ 	  {
+ 	    if (l->fp_offset > 176-16)
+ 	      {
+ 		avalue[i] = l->overflow_arg_area;
+ 		l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
+ 	      }
+ 	    else
+ 	      {
+ 		avalue[i] = (char *)l->reg_save_area + l->fp_offset;
+ 		l->fp_offset += 16;
+ 	      }
+ 	  }
+ #if DEBUG_FFI
+ 	  fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);
+ #endif
+ 	  break;
+ 	  
+ 	default:
+ 	  FFI_ASSERT(0);
+ 	}
+ 
+       argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
+       i++;
+     }
+ 
+   /* Invoke the closure.  */
+   (closure->fun) (cif, rp, avalue, closure->user_data);
+ 
+   /* FIXME: Structs not supported.  */
+   FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);
+ 
+   /* Tell ffi_closure_UNIX64 how to perform return type promotions.  */
+ 
+   return cif->rtype->type;
+ }
  #endif /* ifndef __x86_64__ */
Index: src/x86/unix64.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/x86/unix64.S,v
retrieving revision 1.2
diff -p -2 -c -r1.2 unix64.S
*** src/x86/unix64.S	14 Jan 2003 18:42:29 -0000	1.2
--- src/x86/unix64.S	27 Jan 2003 17:25:35 -0000
*************** sse2floatfloat:
*** 163,167 ****
  	movq	%xmm0, (%rsi)
  	ret
! 	
          .section        .eh_frame,"a",@progbits
  .Lframe0:
--- 163,241 ----
  	movq	%xmm0, (%rsi)
  	ret
! 
! 	.align	2
! .globl ffi_closure_UNIX64
!         .type	ffi_closure_UNIX64,@function
! 
! ffi_closure_UNIX64:
! .LFB2:
!         pushq   %rbp
! .LCFI10:
!         movq    %rsp, %rbp
! .LCFI11:
!         subq    $240, %rsp
! .LCFI12:
! 	movq	%rdi, -176(%rbp)
!         movq    %rsi, -168(%rbp)
!         movq    %rdx, -160(%rbp)
!         movq    %rcx, -152(%rbp)
!         movq    %r8, -144(%rbp)
!         movq    %r9, -136(%rbp)
!         /* FIXME: We can avoid all this stashing of XMM registers by
! 	   (in ffi_prep_closure) computing the number of
! 	   floating-point args and moving it into %rax before calling
! 	   this function.  Once this is done, uncomment the next few
! 	   lines and only the essential XMM rewgisters will be written
! 	   to memory.  This is a significant saving.  */
! /*         movzbl  %al, %eax  */
! /*         movq    %rax, %rdx */
! /*         leaq    0(,%rdx,4), %rax */
! /*         leaq    2f(%rip), %rdx */
! /*         subq    %rax, %rdx */
!         leaq    -1(%rbp), %rax
! /*         jmp     *%rdx */
!         movaps  %xmm7, -15(%rax)
!         movaps  %xmm6, -31(%rax)
!         movaps  %xmm5, -47(%rax)
!         movaps  %xmm4, -63(%rax)
!         movaps  %xmm3, -79(%rax)
!         movaps  %xmm2, -95(%rax)
!         movaps  %xmm1, -111(%rax)
!         movaps  %xmm0, -127(%rax)
! 2:
!         movl    %edi, -180(%rbp)
!         movl    $0, -224(%rbp)
!         movl    $48, -220(%rbp)
!         leaq    16(%rbp), %rax
!         movq    %rax, -216(%rbp)
!         leaq    -176(%rbp), %rdx
!         movq    %rdx, -208(%rbp)
!         leaq    -224(%rbp), %rsi
! 	movq	%r10, %rdi
! 	movq	%rsp, %rdx
!         call    ffi_closure_UNIX64_inner@PLT
! 
! 	cmpl	$FFI_TYPE_FLOAT, %eax
! 	je	1f
! 	cmpl	$FFI_TYPE_DOUBLE, %eax
! 	je	2f
! 	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
! 	je	3f
! 	cmpl	$FFI_TYPE_STRUCT, %eax
! 	je	4f
! 	popq	%rax
!         leave
!         ret
! 1:
! 2:
! 3:	
! 	movaps	-240(%rbp), %xmm0
!         leave
!         ret
! 4:
! 	leave
! 	ret
! .LFE2:	
! 		
          .section        .eh_frame,"a",@progbits
  .Lframe0:
*************** sse2floatfloat:
*** 205,208 ****
--- 279,302 ----
  	.align 8
  .LEFDE1:
+ .LSFDE3:
+         .long   .LEFDE3-.LASFDE3        # FDE Length
+ .LASFDE3:
+         .long   .LASFDE3-.Lframe0       # FDE CIE offset
+ 
+         .long   .LFB2-. # FDE initial location
+         .long   .LFE2-.LFB2     # FDE address range
+         .uleb128 0x0    # Augmentation size
+         .byte   0x4     # DW_CFA_advance_loc4
+         .long   .LCFI10-.LFB2
+         .byte   0xe     # DW_CFA_def_cfa_offset
+         .uleb128 0x10
+         .byte   0x86    # DW_CFA_offset, column 0x6
+         .uleb128 0x2
+         .byte   0x4     # DW_CFA_advance_loc4
+         .long   .LCFI11-.LCFI10
+         .byte   0xd     # DW_CFA_def_cfa_register
+         .uleb128 0x6
+         .align 8
+ .LEFDE3:
  
  #endif /* __x86_64__  */



More information about the Java-patches mailing list