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