diff --git a/src/c/Makefile.in b/src/c/Makefile.in index 9bc843edd..578e81642 100644 --- a/src/c/Makefile.in +++ b/src/c/Makefile.in @@ -96,16 +96,6 @@ apply_x86.c: $(srcdir)/arch/apply_x86.d $(DPP) $(HFILES) ../CROSS-DPP $(srcdir)/arch/apply_x86.d $@ ; \ else $(DPP) $(srcdir)/arch/apply_x86.d $@ ; \ fi -ffi_x86.c: $(srcdir)/arch/ffi_x86.d $(DPP) $(HFILES) - if test -f ../CROSS-DPP ; then \ - ../CROSS-DPP $(srcdir)/arch/ffi_x86.d $@ ; \ - else $(DPP) $(srcdir)/arch/ffi_x86.d $@ ; \ - fi -ffi_x86_64.c: $(srcdir)/arch/ffi_x86_64.d $(DPP) $(HFILES) - if test -f ../CROSS-DPP ; then \ - ../CROSS-DPP $(srcdir)/arch/ffi_x86_64.d $@ ; \ - else $(DPP) $(srcdir)/arch/ffi_x86_64.d $@ ; \ - fi ../libeclmin.a: $(OBJS) all_symbols.o all_symbols2.o $(RM) $@ diff --git a/src/c/arch/ffi_ppc32.d b/src/c/arch/ffi_ppc32.d deleted file mode 100644 index b598a05a4..000000000 --- a/src/c/arch/ffi_ppc32.d +++ /dev/null @@ -1,215 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */ -/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */ - -/* - ffi_x86.c -- Nonportable component of the FFI -*/ -/* - Copyright (c) 2005, Juan Jose Garcia Ripoll. - - ECL is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - See file '../Copyright' for full details. -*/ - -#include -#include -#include - -#error "This file is a placeholder for current development" - -/* - * Calling conventions for OS X under PowerPC/32bit architecture. The rules are - * as follows: - * - * - Registers GPR3-GPR10 are used to pass 32-bit arguments. This includes - * integers and composed data structures which fit in the registers. - * - Registers FPR1-FPR13 are used to pass float and double arguments. - * - For each argument passed in a register, the same amount of memory is - * reserved in the stack. - * - When the amount of registers is exhausted, the remaining arguments are - * passed in the stack. - * - There is a difference between functions whose signature is known and those - * whose is not. In the second case, when passing float/double arguments, - * they are passed redundantly using a GPR, a FPR and the stack. In the - * former case, only the FPR or the stack is used. - * - Since we do not allow functions with varargs (i.e "..." in C parlance), we - * do not care about the last case. - * - * Since we do not allow passing or receiving structures, we need not care - * about it and the only rule is: - * - * - Returns arguments <= 32 bits are stored in GPR3 - * - Returns arguments <= 64 bits are shared between GPR3 and GPR4, for high - * and low bits, respectively. - * - Floating point values are returned in FPR1. - * - * This information appears in "Mac OS X ABI Function Call Guide", from Apple - * Developer's Documentation (April 2006). - */ - -#define MAX_INT_REGISTERS 8 -#define MAX_FP_REGISTERS 13 - -struct ecl_fficall_reg { - long int registers[MAX_INT_REGISTERS]; - int int_registers_size; - double fp_registers[MAX_FP_REGISTERS]; - int fp_registers_size; -}; - -struct ecl_fficall_reg * -ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers) -{ - if (registers == 0) { - registers = (struct ecl_fficall_reg *)cl_alloc_atomic(sizeof(*registers)); - } - registers->int_registers_size = 0; - registers->fp_registers_size = 0; -} - -void -ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type) -{ - long i; - struct ecl_fficall *fficall = cl_env.fficall; - struct ecl_fficall_reg *registers = cl_env.fficall->registers; - switch (type) { - case ECL_FFI_CHAR: i = data->c; goto INT; - case ECL_FFI_UNSIGNED_CHAR: i = data->uc; goto INT; - case ECL_FFI_BYTE: i = data->b; goto INT; - case ECL_FFI_UNSIGNED_BYTE: i = data->ub; goto INT; - case ECL_FFI_SHORT: i = data->s; goto INT; - case ECL_FFI_UNSIGNED_SHORT: i = data->us; goto INT; - case ECL_FFI_INT: i = data->i; goto INT; - case ECL_FFI_UNSIGNED_INT: i = data->ui; goto INT; - case ECL_FFI_LONG: - case ECL_FFI_UNSIGNED_LONG: - case ECL_FFI_POINTER_VOID: - case ECL_FFI_CSTRING: - case ECL_FFI_OBJECT: - i = data->l; - INT: - if (registers->int_registers_size < MAX_INT_REGISTERS) { - registers->registers[registers->int_registers_size++] = i; - } - ecl_fficall_align(sizeof(long)); - ecl_fficall_push_bytes(&i, sizeof(long)); - break; - case ECL_FFI_DOUBLE: - if (registers->fp_registers_size < MAX_FP_REGISTERS) { - registers->fp_registers[registers->fp_registers_size++] = data->d; - registers->int_registers_size += 2; - } - ecl_fficall_align(sizeof(long)); - ecl_fficall_push_bytes(&data->d, sizeof(double), sizeof(long)); - break; - case ECL_FFI_FLOAT: - if (registers->fp_registers_size < MAX_FP_REGISTERS) { - registers->fp_registers[registers->fp_registers_size++] = data->f; - registers->int_registers_size++; - } - ecl_fficall_align(sizeof(long)); - ecl_fficall_push_bytes(&data->f, sizeof(float), sizeof(long)); - break; - case ECL_FFI_VOID: - FEerror("VOID is not a valid argument type for a C function", 0); - } -} - -static void -ecl_fficall_do_execute(cl_index buf_size, void *stack, void *gpr, void *gpfr, void *f) -{ -} - -void -ecl_fficall_execute(void *_f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type) -{ - struct ecl_fficall_reg *registers = fficall->registers; - long bufsize = fficall->buffer_size; - char* buf = fficall->buffer; - - asm volatile ( - "mr r5,%[bufsize]\n\t" /* r5 = size of stack */ - "mr r6,%[buf]\n\t" /* r6 = origin of stack data */ - "mr r17,%[registers]\n\t" /* r17 = origin of integer registers */ - "mr r16,%[fp_registers]\n\t"/* r16 = origin of fp registers */ - "mr r15,%[fptr]\n\t" /* r15 = _f_ptr */ - "mr r29, r1\n\t" /* r29 saves r1 */ - - "subf r13,r5,r1\n\t" - "stwu r13,-80(r13)\n\t" /* r13 <- r1 - r5 - 80 */ - "mflr r0\n\t" - "stw r0,8(r1)\n\t" - "mr r1,r13\n\t" /* r1 <- r13 */ - - "stwu r14,24(r1)\n\t" /* r14 <- begin of parameters */ - "cmpwi cr0,r5,0\n\t" /* copy r5 bytes from (r6) to (r14) */ - "ble cr0,L3\n\t" - "mtctr r5\n" -"LX: lbz r0,0(r6)\n\t" - "addi r6,r6,1\n\t" - "stb r0,0(r14)\n\t" - "addi r14,r14,1\n" -"L3: lfd f1, 0(r16)\n\t" /* load fp registers from (r16) */ - "lfd f2, 8(r16)\n\t" - "lfd f3, 16(r16)\n\t" - "lfd f4, 24(r16)\n\t" - "lfd f5, 32(r16)\n\t" - "lfd f6, 40(r16)\n\t" - "lfd f7, 48(r16)\n\t" - "lfd f8, 56(r16)\n\t" - "lfd f9, 64(r16)\n\t" - "lfd f10, 72(r16)\n\t" - "lfd f11, 80(r16)\n\t" - "lfd f12, 88(r16)\n\t" - "lfd f13, 96(r16)\n\t" - - "lwz r6, 16(r17)\n\t" /* load int registers from (r17) */ - "lwz r7, 20(r17)\n\t" - "lwz r8, 24(r17)\n\t" - "lwz r9, 28(r17)\n\t" - "lwz r10, 32(r17)\n\t" - "lwz r5, 8(r17)\n\t" - "lwz r4, 4(r17)\n\t" - "lwz r3, 0(r17)\n\t" - - "mtctr r15\n\t" /* call the function stored in r15 */ - "bctrl \n\t" - "mr r1,r29\n\t" /* restore stack and return pointer */ - "lwz r0,8(r1)\n\t" - "mtlr r0\n\t" - "stw r3,0(r17)\n\t" /* store function's output */ - "stw r4,4(r17)\n\t" - "stfd f1,0(r16)\n\t" - - :: [bufsize] "r" (bufsize), [buf] "r" (buf), [registers] "r" (registers->registers), - [fp_registers] "r" (registers->fp_registers), [fptr] "r" (_f_ptr) - : "r5","r6","r17","r16","r29","r13","r14"); - - - void *data = registers->registers; - if (return_type <= ECL_FFI_UNSIGNED_LONG) { - fficall->output.i = *((unsigned long *)data); - } else if (return_type == ECL_FFI_POINTER_VOID) { - fficall->output.pv = *((void **)data); - } else if (return_type == ECL_FFI_CSTRING) { - fficall->output.pc = *((char *)data); - } else if (return_type == ECL_FFI_OBJECT) { - fficall->output.o = *((cl_object *)data); - } else if (return_type == ECL_FFI_FLOAT) { - fficall->output.f = registers->fp_registers[0]; - } else if (return_type == ECL_FFI_DOUBLE) { - fficall->output.d = registers->fp_registers[0]; - } -} - - -void* -ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type) -{ - exit(0); -} diff --git a/src/c/arch/ffi_x86.d b/src/c/arch/ffi_x86.d deleted file mode 100644 index c11f6f0e0..000000000 --- a/src/c/arch/ffi_x86.d +++ /dev/null @@ -1,342 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */ -/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */ - -/* - ffi_x86.c -- Nonportable component of the FFI -*/ -/* - Copyright (c) 2005, Juan Jose Garcia Ripoll. - - ECL is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - See file '../Copyright' for full details. -*/ - -#include -#include -#include - -#if !defined(HAVE_LIBFFI) - -struct ecl_fficall_reg * -ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers) -{ - /* No need to prepare registers */ - return 0; -} - -void -ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type) -{ - int i; - switch (type) { - case ECL_FFI_CHAR: i = data->c; goto INT_ECL; - case ECL_FFI_UNSIGNED_CHAR: i = data->uc; goto INT_ECL; - case ECL_FFI_BYTE: i = data->b; goto INT_ECL; - case ECL_FFI_UNSIGNED_BYTE: i = data->ub; goto INT_ECL; - case ECL_FFI_SHORT: i = data->s; goto INT_ECL; - case ECL_FFI_UNSIGNED_SHORT: i = data->us; goto INT_ECL; -#ifdef ecl_uint8_t - case ECL_FFI_INT8_T: i = data->i8; goto INT_ECL; - case ECL_FFI_UINT8_T: i = data->u8; goto INT_ECL; -#endif -#ifdef ecl_uint16_t - case ECL_FFI_INT16_T: i = data->i16; goto INT_ECL; - case ECL_FFI_UINT16_T: i = data->u16; goto INT_ECL; -#endif - case ECL_FFI_INT: - case ECL_FFI_LONG: - case ECL_FFI_UNSIGNED_INT: - case ECL_FFI_UNSIGNED_LONG: -#ifdef ecl_uint32_t - case ECL_FFI_INT32_T: - case ECL_FFI_UINT32_T: -#endif - case ECL_FFI_POINTER_VOID: - case ECL_FFI_CSTRING: - case ECL_FFI_OBJECT: - i = data->i; - INT_ECL: - ecl_fficall_align(sizeof(int)); - ecl_fficall_push_int(i); - break; - case ECL_FFI_DOUBLE: - ecl_fficall_align(sizeof(int)); - ecl_fficall_push_bytes(&data->d, sizeof(double)); - break; - case ECL_FFI_FLOAT: - ecl_fficall_align(sizeof(int)); - ecl_fficall_push_bytes(&data->f, sizeof(float)); - break; -#ifdef ecl_uint64_t - case ECL_FFI_UINT64_T: - case ECL_FFI_INT64_T: - ecl_fficall_align(sizeof(ecl_uint64_t)); - ecl_fficall_push_bytes(&data->ull, sizeof(ecl_uint64_t)); - break; -#endif -#ifdef ecl_long_long_t - case ECL_FFI_UNSIGNED_LONG_LONG: - case ECL_FFI_LONG_LONG: - ecl_fficall_align(sizeof(unsigned long)); - ecl_fficall_push_bytes(&data->ull, sizeof(unsigned long long)); - break; -#endif - case ECL_FFI_VOID: - FEerror("VOID is not a valid argument type for a C function", 0); - } -} - -void -ecl_fficall_execute(void *f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type) -{ - int bufsize = fficall->buffer_size; - char* buf = fficall->buffer; - char* stack_p; -#ifdef _MSC_VER - __asm - { - mov stack_p,esp - sub esp,bufsize - mov esi,buf - mov edi,esp - mov ecx,bufsize - rep movsb - } -#else - asm volatile ( - "movl %%esp, %0\n\t" - "subl %1, %%esp\n\t" - "movl %2, %%esi\n\t" - "movl %%esp, %%edi\n\t" - "rep\n\t" - "movsb\n\t" - : "=a" (stack_p) : "c" (bufsize), "d" (buf) : "%edi", "%esi"); -#endif - if (return_type <= ECL_FFI_UNSIGNED_LONG) { - fficall->output.i = ((int (*)())f_ptr)(); - } else if (return_type == ECL_FFI_POINTER_VOID) { - fficall->output.pv = ((void * (*)())f_ptr)(); - } else if (return_type == ECL_FFI_CSTRING) { - fficall->output.pc = ((char * (*)())f_ptr)(); - } else if (return_type == ECL_FFI_OBJECT) { - fficall->output.o = ((cl_object (*)())f_ptr)(); - } else if (return_type == ECL_FFI_FLOAT) { - fficall->output.f = ((float (*)())f_ptr)(); - } else if (return_type == ECL_FFI_DOUBLE) { - fficall->output.d = ((double (*)())f_ptr)(); - } -#ifdef ecl_uint8_t - else if (return_type == ECL_FFI_INT8_T) { - fficall->output.i8 = ((ecl_int8_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT16_T) { - fficall->output.u8 = ((ecl_uint8_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_uint16_t - else if (return_type == ECL_FFI_INT16_T) { - fficall->output.i16 = ((ecl_int16_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT16_T) { - fficall->output.u16 = ((ecl_uint16_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_uint32_t - else if (return_type == ECL_FFI_INT32_T) { - fficall->output.i32 = ((ecl_int32_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT32_T) { - fficall->output.u32 = ((ecl_uint32_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_uint64_t - else if (return_type == ECL_FFI_INT64_T) { - fficall->output.i64 = ((ecl_int64_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT32_T) { - fficall->output.u64 = ((ecl_uint64_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_long_long_t - else if (return_type == ECL_FFI_LONG_LONG) { - fficall->output.ll = ((ecl_long_long_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UNSIGNED_LONG_LONG) { - fficall->output.ull = ((ecl_ulong_long_t (*)())f_ptr)(); - } -#endif - else { - ((void (*)())f_ptr)(); - } -#ifdef _MSC_VER - __asm mov esp,stack_p -#else - asm volatile ("mov %0,%%esp" :: "a" (stack_p)); -#endif -} - -static void -ecl_dynamic_callback_execute(cl_object cbk_info, char *arg_buffer) -{ - cl_object fun, rtype, argtypes; - cl_object result; - cl_index i, size; - union ecl_ffi_values output; - enum ecl_ffi_tag tag; - cl_env_ptr env = ecl_process_env(); - - ECL_BUILD_STACK_FRAME(env, frame, aux); - - fun = CAR(cbk_info); - rtype = CADR(cbk_info); - argtypes = CADDR(cbk_info); - - arg_buffer += 4; /* Skip return address */ - for (i=0; !ecl_endp(argtypes); argtypes = CDR(argtypes), i++) { - tag = ecl_foreign_type_code(CAR(argtypes)); - size = ecl_fixnum(si_size_of_foreign_elt_type(CAR(argtypes))); - result = ecl_foreign_data_ref_elt(arg_buffer, tag); - ecl_stack_frame_push(frame,result); - { - int mask = 3; - int sp = (size + mask) & ~mask; - arg_buffer += (sp); - } - } - - result = ecl_apply_from_stack_frame(frame, fun); - ecl_stack_frame_close(frame); - - tag = ecl_foreign_type_code(rtype); - memset(&output, 0, sizeof(output)); - ecl_foreign_data_set_elt(&output, tag, result); - - switch (tag) { - case ECL_FFI_CHAR: i = output.c; goto INT_ECL; - case ECL_FFI_UNSIGNED_CHAR: i = output.uc; goto INT_ECL; - case ECL_FFI_BYTE: i = output.b; goto INT_ECL; - case ECL_FFI_UNSIGNED_BYTE: i = output.ub; goto INT_ECL; -#ifdef ecl_uint8_t - case ECL_FFI_INT8_T: i = output.i8; goto INT_ECL; - case ECL_FFI_UINT8_T: i = output.u8; goto INT_ECL; -#endif -#ifdef ecl_uint16_t - case ECL_FFI_INT16_T: -#endif - case ECL_FFI_SHORT: i = output.s; goto INT_ECL; -#ifdef ecl_uint16_t - case ECL_FFI_UINT16_T: -#endif - case ECL_FFI_UNSIGNED_SHORT: i = output.us; goto INT_ECL; - case ECL_FFI_POINTER_VOID: - case ECL_FFI_OBJECT: - case ECL_FFI_CSTRING: - case ECL_FFI_INT: - case ECL_FFI_UNSIGNED_INT: -#ifdef ecl_uint32_t - case ECL_FFI_INT32_T: - case ECL_FFI_UINT32_T: -#endif - case ECL_FFI_LONG: - case ECL_FFI_UNSIGNED_LONG: - i = output.i; -INT_ECL: -#ifdef _MSC_VER - __asm mov eax,i -#else - { - register int eax asm("eax"); - eax = i; - } -#endif - return; -#if defined(ecl_long_long_t) || defined(ecl_uint64_t) -# ifdef ecl_long_long_t - case ECL_FFI_LONG_LONG: - case ECL_FFI_UNSIGNED_LONG_LONG: -# endif -# ifdef ecl_uint64_t - case ECL_FFI_INT64_T: - case ECL_FFI_UINT64_T: -# endif -# ifdef _MSC_VER - __asm mov eax,output.l2[0] - __asm mov edx,output.l2[1] -# else - { - register int eax asm("eax"); - register int edx asm("edx"); - eax = output.l2[0]; - edx = output.l2[1]; - } -# endif - return; -#endif /* ecl_long_long_t */ - case ECL_FFI_DOUBLE: { -#ifdef _MSC_VER - __asm fld output.d -#else - { - asm("fldl (%0)" :: "a" (&output.d)); - } -#endif - return; - } - case ECL_FFI_FLOAT: { -#ifdef _MSC_VER - __asm fld output.f -#else - { - asm("flds (%0)" :: "a" (&output.f)); - } -#endif - return; - } - case ECL_FFI_VOID: - return; - } -} - -void* -ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type) -{ - /* - * push %esp 54 - * pushl 68 - * call ecl_dynamic_callback_call E8 - * [ Here we could use also lea 4(%esp), %esp, but %ecx seems to be free ] - * pop %ecx 59 - * pop %ecx 59 - * ret c3 - * nop 90 - * nop 90 - */ - char *buf = (char*)ecl_alloc_atomic_align(sizeof(char)*16, 4); - *(char*) (buf+0) = 0x54; - *(char*) (buf+1) = 0x68; - *(long*) (buf+2) = (long)data; - *(unsigned char*) (buf+6) = 0xE8; - *(long*) (buf+7) = (long)ecl_dynamic_callback_execute - (long)(buf+11); - *(char*) (buf+11) = 0x59; - *(char*) (buf+12) = 0x59; - if (cc_type == ECL_FFI_CC_CDECL) { - *(unsigned char*) (buf+13) = 0xc3; - *(unsigned short*)(buf+14) = 0x9090; - } else { - cl_object arg_types = CADDR(data); - int byte_size = 0; - int mask = 3; - - while (CONSP(arg_types)) { - int sz = ecl_fixnum(si_size_of_foreign_elt_type(CAR(arg_types))); - byte_size += ((sz+mask)&(~mask)); - arg_types = CDR(arg_types); - } - - *(unsigned char*) (buf+13) = 0xc2; - *(unsigned short*)(buf+14) = (unsigned short)byte_size; - } - - return buf; -} - -#endif diff --git a/src/c/arch/ffi_x86_64.d b/src/c/arch/ffi_x86_64.d deleted file mode 100644 index b368310a5..000000000 --- a/src/c/arch/ffi_x86_64.d +++ /dev/null @@ -1,370 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */ -/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */ - -/* - ffi_x86.c -- Nonportable component of the FFI -*/ -/* - Copyright (c) 2005, Juan Jose Garcia Ripoll. - - ECL is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - See file '../Copyright' for full details. -*/ - -#include -#include -#include - -#if !defined(HAVE_LIBFFI) - -#define MAX_INT_REGISTERS 6 -#define MAX_FP_REGISTERS 8 - -struct ecl_fficall_reg { - long int_registers[MAX_INT_REGISTERS]; - int int_registers_size; - double fp_registers[MAX_FP_REGISTERS]; - int fp_registers_size; -}; - -struct ecl_fficall_reg * -ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers) -{ - if (registers == 0) { - registers = ecl_alloc_atomic_align(sizeof(*registers), sizeof(long)); - } - registers->int_registers_size = 0; - registers->fp_registers_size = 0; - return registers; -} - -void -ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type) -{ - long i; - struct ecl_fficall *fficall = cl_env.fficall; - struct ecl_fficall_reg *registers = fficall->registers; - switch (type) { - case ECL_FFI_CHAR: i = data->c; goto INT; - case ECL_FFI_UNSIGNED_CHAR: i = data->uc; goto INT; -#ifdef ecl_uint8_t - case ECL_FFI_INT8_T: i = data->i8; goto INT; - case ECL_FFI_UINT8_T: i = data->u8; goto INT; -#endif - case ECL_FFI_BYTE: i = data->b; goto INT; - case ECL_FFI_UNSIGNED_BYTE: i = data->ub; goto INT; -#ifdef ecl_uint16_t - case ECL_FFI_INT16_T: i = data->i16; goto INT; - case ECL_FFI_UINT16_T: i = data->u16; goto INT; -#endif - case ECL_FFI_SHORT: i = data->s; goto INT; - case ECL_FFI_UNSIGNED_SHORT: i = data->us; goto INT; -#ifdef ecl_uint32_t - case ECL_FFI_INT32_T: i = data->i32; goto INT; - case ECL_FFI_UINT32_T: i = data->u32; goto INT; -#endif - case ECL_FFI_INT: i = data->i; goto INT; - case ECL_FFI_UNSIGNED_INT: i = data->ui; goto INT; - case ECL_FFI_LONG: - case ECL_FFI_UNSIGNED_LONG: -#ifdef ecl_uint64_t - case ECL_FFI_INT64_T: - case ECL_FFI_UINT64_T: -#endif - case ECL_FFI_POINTER_VOID: - case ECL_FFI_CSTRING: - case ECL_FFI_OBJECT: - i = data->l; - INT: - if (registers->int_registers_size < MAX_INT_REGISTERS) { - registers->int_registers[registers->int_registers_size++] = i; - } else { - ecl_fficall_align(sizeof(long)); - ecl_fficall_push_bytes(&i, sizeof(long)); - } - break; - case ECL_FFI_DOUBLE: - if (registers->fp_registers_size < MAX_FP_REGISTERS) { - registers->fp_registers[registers->fp_registers_size++] = data->d; - } else { - ecl_fficall_align(sizeof(long)); - ecl_fficall_push_bytes(&data->d, sizeof(double)); - } - break; - case ECL_FFI_FLOAT: - if (registers->fp_registers_size < MAX_FP_REGISTERS) { - memset(®isters->fp_registers[registers->fp_registers_size], 0, sizeof(double)); - (*(float*)(®isters->fp_registers[registers->fp_registers_size++])) = (float)data->f; - } else { - i = 0; - ecl_fficall_align(sizeof(long)); - ecl_fficall_push_bytes(&data->f, sizeof(float)); - ecl_fficall_push_bytes(&i, sizeof(float)); - } - break; - case ECL_FFI_VOID: - FEerror("VOID is not a valid argument type for a C function", 0); - } -} - -void -ecl_fficall_execute(void *_f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type) -{ - struct ecl_fficall_reg *registers = fficall->registers; - long bufsize = fficall->buffer_size; - char* buf = fficall->buffer; - char* stack_p; - register void* f_ptr asm("r10"); - - ecl_fficall_align(16); - bufsize = fficall->buffer_size; - f_ptr = _f_ptr; - - asm volatile ( - "mov %%rsp, %0\n\t" - "sub %1, %%rsp\n\t" - "mov %2, %%rsi\n\t" - "mov %%rsp, %%rdi\n\t" - "rep\n\t" - "movsb\n\t" - : "=a" (stack_p) : "c" (bufsize), "d" (buf) : "%rdi", "%rsi"); - - asm volatile ( - "mov (%%rax), %%rdi\n\t" - "mov 0x08(%%rax), %%rsi\n\t" - "mov 0x10(%%rax), %%rdx\n\t" - "mov 0x18(%%rax), %%rcx\n\t" - "mov 0x20(%%rax), %%r8\n\t" - "mov 0x28(%%rax), %%r9\n\t" - :: "a" (registers->int_registers)); - - asm volatile ( - "movsd (%%rax), %%xmm0\n\t" - "movsd 0x08(%%rax), %%xmm1\n\t" - "movsd 0x10(%%rax), %%xmm2\n\t" - "movsd 0x18(%%rax), %%xmm3\n\t" - "movsd 0x20(%%rax), %%xmm4\n\t" - "movsd 0x28(%%rax), %%xmm5\n\t" - "movsd 0x30(%%rax), %%xmm6\n\t" - "movsd 0x38(%%rax), %%xmm7\n\t" - :: "a" (registers->fp_registers)); - - if (return_type <= ECL_FFI_UNSIGNED_LONG) { - fficall->output.ul = ((unsigned long (*)())f_ptr)(); - } else if (return_type == ECL_FFI_POINTER_VOID) { - fficall->output.pv = ((void * (*)())f_ptr)(); - } else if (return_type == ECL_FFI_CSTRING) { - fficall->output.pc = ((char * (*)())f_ptr)(); - } else if (return_type == ECL_FFI_OBJECT) { - fficall->output.o = ((cl_object (*)())f_ptr)(); - } else if (return_type == ECL_FFI_FLOAT) { - fficall->output.f = ((float (*)())f_ptr)(); - } else if (return_type == ECL_FFI_DOUBLE) { - fficall->output.d = ((double (*)())f_ptr)(); - } -#ifdef ecl_uint8_t - else if (return_type == ECL_FFI_INT8_T) { - fficall->output.i8 = ((ecl_int8_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT16_T) { - fficall->output.u8 = ((ecl_uint8_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_uint16_t - else if (return_type == ECL_FFI_INT16_T) { - fficall->output.i16 = ((ecl_int16_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT16_T) { - fficall->output.u16 = ((ecl_uint16_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_uint32_t - else if (return_type == ECL_FFI_INT32_T) { - fficall->output.i32 = ((ecl_int32_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT32_T) { - fficall->output.u32 = ((ecl_uint32_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_uint64_t - else if (return_type == ECL_FFI_INT64_T) { - fficall->output.i64 = ((ecl_int64_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UINT32_T) { - fficall->output.u64 = ((ecl_uint64_t (*)())f_ptr)(); - } -#endif -#ifdef ecl_long_long_t - else if (return_type == ECL_FFI_LONG_LONG) { - fficall->output.ll = ((ecl_long_long_t (*)())f_ptr)(); - } else if (return_type == ECL_FFI_UNSIGNED_LONG_LONG) { - fficall->output.ull = ((ecl_ulong_long_t (*)())f_ptr)(); - } -#endif - else { - ((void (*)())f_ptr)(); - } - - asm volatile ("mov %0,%%rsp" :: "a" (stack_p)); -} - -static void -ecl_dynamic_callback_execute(long i1, long i2, long i3, long i4, long i5, long i6, - double f1, double f2, double f3, double f4, - double f5, double f6, double f7, double f8, - cl_object cbk_info, char *arg_buffer) -{ - cl_object fun, rtype, argtypes; - cl_object result; - cl_index i, size, i_reg_index, f_reg_index; - union ecl_ffi_values output; - enum ecl_ffi_tag tag; - long i_reg[MAX_INT_REGISTERS]; - double f_reg[MAX_FP_REGISTERS]; - cl_env_ptr env = ecl_process_env(); - - ECL_BUILD_STACK_FRAME(env, frame, aux); - - fun = CAR(cbk_info); - rtype = CADR(cbk_info); - argtypes = CADDR(cbk_info); - - i_reg_index = f_reg_index = 0; - i_reg[0] = i1; - i_reg[1] = i2; - i_reg[2] = i3; - i_reg[3] = i4; - i_reg[4] = i5; - i_reg[5] = i6; - f_reg[0] = f1; - f_reg[1] = f2; - f_reg[2] = f3; - f_reg[3] = f4; - f_reg[4] = f5; - f_reg[5] = f6; - f_reg[6] = f7; - f_reg[7] = f8; - - arg_buffer += 2*sizeof(void*); /* Skip return address and base pointer */ - for (i=0; !ecl_endp(argtypes); argtypes = CDR(argtypes), i++) { - tag = ecl_foreign_type_code(CAR(argtypes)); - size = ecl_fixnum(si_size_of_foreign_elt_type(CAR(argtypes))); - if (tag <= ECL_FFI_OBJECT) { - if (i_reg_index < MAX_INT_REGISTERS) - result = ecl_foreign_data_ref_elt(&i_reg[i_reg_index++], tag); - else - goto ARG_FROM_STACK; - } else if (tag <= ECL_FFI_DOUBLE) { - if (f_reg_index < MAX_FP_REGISTERS) - result = ecl_foreign_data_ref_elt(&f_reg[f_reg_index++], tag); - else - goto ARG_FROM_STACK; - } else { -ARG_FROM_STACK: - result = ecl_foreign_data_ref_elt(arg_buffer, tag); - { - int mask = 7; - int sp = (size + mask) & ~mask; - arg_buffer += (sp); - } - } - ecl_stack_frame_push(frame, result); - } - - result = ecl_apply_from_stack_frame(frame, fun); - ecl_stack_frame_close(frame); - - tag = ecl_foreign_type_code(rtype); - memset(&output, 0, sizeof(output)); - ecl_foreign_data_set_elt(&output, tag, result); - - switch (tag) { - case ECL_FFI_CHAR: i = output.c; goto INT; - case ECL_FFI_UNSIGNED_CHAR: i = output.uc; goto INT; - case ECL_FFI_BYTE: i = output.b; goto INT; - case ECL_FFI_UNSIGNED_BYTE: i = output.ub; goto INT; -#ifdef ecl_uint8_t - case ECL_FFI_INT8_T: i = output.i8; goto INT; - case ECL_FFI_UINT8_T: i = output.u8; goto INT; -#endif -#ifdef ecl_uint16_t - case ECL_FFI_INT16_T: i = output.i16; goto INT; - case ECL_FFI_UINT16_T: i = output.u16; goto INT; -#endif - case ECL_FFI_SHORT: i = output.s; goto INT; - case ECL_FFI_UNSIGNED_SHORT: i = output.us; goto INT; -#ifdef ecl_uint32_t - case ECL_FFI_INT32_T: i = output.i32; goto INT; - case ECL_FFI_UINT32_T: i = output.u32; goto INT; -#endif - case ECL_FFI_POINTER_VOID: - case ECL_FFI_OBJECT: - case ECL_FFI_CSTRING: - case ECL_FFI_INT: - case ECL_FFI_UNSIGNED_INT: - case ECL_FFI_LONG: - case ECL_FFI_UNSIGNED_LONG: -#ifdef ecl_uint64_t - case ECL_FFI_INT64_T: - case ECL_FFI_UINT64_T: -#endif - i = output.i; -INT: - { - register long eax asm("rax"); - eax = i; - } - return; - case ECL_FFI_DOUBLE: { - { - asm("movsd (%0),%%xmm0" :: "a" (&output.d)); - } - return; - } - case ECL_FFI_FLOAT: { - { - asm("movss (%0),%%xmm0" :: "a" (&output.f)); - } - return; - } - case ECL_FFI_VOID: - return; - } -} - -void* -ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type) -{ - /* - * push %rbp 55 - * push %rsp 54 - * mov ,%rax 48 b8 - * push %rax 50 - * mov ,%rax 48 b8 - * callq *%rax 48 ff d0 - * pop %rcx 59 - * pop %rcx 59 - * pop %rbp 5d - * ret c3 - * nop 90 - * nop 90 - */ - char *buf = (char*)ecl_alloc_atomic_align(sizeof(char)*32, 8); - *(char*) (buf+0) = 0x55; - *(char*) (buf+1) = 0x54; - *(short*)(buf+2) = 0xb848; - *(long*) (buf+4) = (long)data; - *(char*) (buf+12) = 0x50; - *(short*)(buf+13) = 0xb848; - *(long*) (buf+15) = (long)ecl_dynamic_callback_execute; - *(int*) (buf+23) = (int)0x00d0ff48; /* leading null byte is overwritten */ - *(char*) (buf+26) = 0x59; - *(char*) (buf+27) = 0x59; - *(char*) (buf+28) = 0x5d; - *(char*) (buf+29) = 0xc3; - *(short*)(buf+30) = 0x9090; - - return buf; -} - -#endif diff --git a/src/c/ecl_features.h b/src/c/ecl_features.h index 482843891..0cf06ee0f 100644 --- a/src/c/ecl_features.h +++ b/src/c/ecl_features.h @@ -74,7 +74,7 @@ ecl_def_string_array(feature_names,static,const) = { #ifdef ECL_CLOS_STREAMS ecl_def_string_array_elt("CLOS-STREAMS"), #endif -#if defined(ECL_DYNAMIC_FFI) || defined(HAVE_LIBFFI) +#if defined(HAVE_LIBFFI) ecl_def_string_array_elt("DFFI"), #endif #ifdef ECL_UNICODE diff --git a/src/c/ffi.d b/src/c/ffi.d index 8861303e6..ee46060ad 100644 --- a/src/c/ffi.d +++ b/src/c/ffi.d @@ -125,13 +125,6 @@ ecl_foreign_type_table[] = { {@':void', 0, 0} }; -#ifdef ECL_DYNAMIC_FFI -static const cl_object ecl_foreign_cc_table[] = { - @':cdecl', - @':stdcall' -}; -#endif - #ifdef HAVE_LIBFFI static struct { const cl_object symbol; @@ -433,20 +426,6 @@ ecl_foreign_cc_code(cl_object cc) } #endif -#ifdef ECL_DYNAMIC_FFI -enum ecl_ffi_calling_convention -ecl_foreign_cc_code(cl_object cc) -{ - int i; - for (i = 0; i <= ECL_FFI_CC_STDCALL; i++) { - if (cc == ecl_foreign_cc_table[i]) - return (enum ecl_ffi_calling_convention)i; - } - FEerror("~A does no denote a valid calling convention.", 1, cc); - return ECL_FFI_CC_CDECL; -} -#endif - static void wrong_ffi_tag(enum ecl_ffi_tag tag) ecl_attr_noreturn; static void @@ -784,108 +763,6 @@ OUTPUT: #endif } -#ifdef ECL_DYNAMIC_FFI -static void -ecl_fficall_overflow() -{ - FEerror("Stack overflow on SI:CALL-CFUN", 0); -} - -void -ecl_fficall_prepare(cl_object return_type, cl_object arg_type, cl_object cc_type) -{ - struct ecl_fficall *fficall = cl_env.fficall; - fficall->buffer_sp = fficall->buffer; - fficall->buffer_size = 0; - fficall->cstring = ECL_NIL; - fficall->cc = ecl_foreign_cc_code(cc_type); - fficall->registers = ecl_fficall_prepare_extra(fficall->registers); -} - -void -ecl_fficall_push_bytes(void *data, size_t bytes) -{ - struct ecl_fficall *fficall = cl_env.fficall; - fficall->buffer_size += bytes; - if (fficall->buffer_size >= ECL_FFICALL_LIMIT) - ecl_fficall_overflow(); - memcpy(fficall->buffer_sp, (char*)data, bytes); - fficall->buffer_sp += bytes; -} - -void -ecl_fficall_push_int(int data) -{ - ecl_fficall_push_bytes(&data, sizeof(int)); -} - -void -ecl_fficall_align(int data) -{ - struct ecl_fficall *fficall = cl_env.fficall; - if (data == 1) - return; - else { - size_t sp = fficall->buffer_sp - fficall->buffer; - size_t mask = data - 1; - size_t new_sp = (sp + mask) & ~mask; - if (new_sp >= ECL_FFICALL_LIMIT) - ecl_fficall_overflow(); - fficall->buffer_sp = fficall->buffer + new_sp; - fficall->buffer_size = new_sp; - } -} - -@(defun si::call-cfun (fun return_type arg_types args &optional (cc_type @':cdecl')) - struct ecl_fficall *fficall = cl_env.fficall; - void *cfun = ecl_foreign_data_pointer_safe(fun); - cl_object object; - enum ecl_ffi_tag return_type_tag = ecl_foreign_type_code(return_type); -@ - - ecl_fficall_prepare(return_type, arg_types, cc_type); - while (CONSP(arg_types)) { - enum ecl_ffi_tag type; - if (!CONSP(args)) { - FEerror("In SI:CALL-CFUN, mismatch between argument types and argument list: ~A vs ~A", 0); - } - type = ecl_foreign_type_code(CAR(arg_types)); - if (type == ECL_FFI_CSTRING) { - object = ecl_null_terminated_base_string(CAR(args)); - if (CAR(args) != object) - fficall->cstring = - CONS(object, fficall->cstring); - } else { - object = CAR(args); - } - ecl_foreign_data_set_elt(&fficall->output, type, object); - ecl_fficall_push_arg(&fficall->output, type); - arg_types = CDR(arg_types); - args = CDR(args); - } - ecl_fficall_execute(cfun, fficall, return_type_tag); - object = ecl_foreign_data_ref_elt(&fficall->output, return_type_tag); - - fficall->buffer_size = 0; - fficall->buffer_sp = fficall->buffer; - fficall->cstring = ECL_NIL; - - @(return object) -@) - -@(defun si::make-dynamic-callback (fun sym rtype argtypes &optional (cctype @':cdecl')) - cl_object data; - cl_object cbk; -@ - data = cl_list(3, fun, rtype, argtypes); - cbk = ecl_make_foreign_data(@':pointer-void', 0, ecl_dynamic_callback_make(data, ecl_foreign_cc_code(cctype))); - - si_put_sysprop(sym, @':callback', CONS(cbk, data)); - @(return cbk) -@) -#endif /* ECL_DYNAMIC_FFI */ - - #ifdef HAVE_LIBFFI static void resize_call_stack(cl_env_ptr env, cl_index new_size) diff --git a/src/c/main.d b/src/c/main.d index 3c9044874..d03da3417 100755 --- a/src/c/main.d +++ b/src/c/main.d @@ -164,10 +164,6 @@ ecl_init_env(cl_env_ptr env) env->ffi_values = 0; env->ffi_values_ptrs = 0; #endif -#ifdef ECL_DYNAMIC_FFI - env->fficall = ecl_alloc(sizeof(struct ecl_fficall)); - ((struct ecl_fficall*)env->fficall)->registers = 0; -#endif env->method_cache = ecl_make_cache(64, 4096); env->slot_cache = ecl_make_cache(3, 4096); diff --git a/src/c/symbols_list.h b/src/c/symbols_list.h index 3c124dd3f..04f0b26d4 100755 --- a/src/c/symbols_list.h +++ b/src/c/symbols_list.h @@ -71,16 +71,11 @@ typedef struct { #else # define IF_SSE2(x) NULL #endif -#if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) +#if defined(HAVE_LIBFFI) # define IF_DFFI(x) x #else # define IF_DFFI(x) NULL #endif -#if defined(HAVE_LIBFFI) -# define IF_LIBFFI(x) x -#else -# define IF_LIBFFI(x) NULL -#endif cl_symbol_initializer cl_symbols[] = { @@ -1749,12 +1744,12 @@ cl_symbols[] = { {SYS_ "*CODE-WALKER*", SI_SPECIAL, NULL, -1, OBJNULL}, -/* #if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */ +/* #if defined(HAVE_LIBFFI) */ {SYS_ "CALL-CFUN", SI_ORDINARY, IF_DFFI(si_call_cfun), -1, OBJNULL}, {KEY_ "CALLBACK", KEYWORD, NULL, -1, OBJNULL}, {SYS_ "MAKE-DYNAMIC-CALLBACK", SI_ORDINARY, IF_DFFI(si_make_dynamic_callback), -1, OBJNULL}, -{SYS_ "FREE-FFI-CLOSURE", SI_ORDINARY, IF_LIBFFI(si_free_ffi_closure), 1, OBJNULL}, -/* #endif defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */ +{SYS_ "FREE-FFI-CLOSURE", SI_ORDINARY, IF_DFFI(si_free_ffi_closure), 1, OBJNULL}, +/* #endif defined(HAVE_LIBFFI) */ {KEY_ "CDECL", KEYWORD, NULL, -1, OBJNULL}, {KEY_ "STDCALL", KEYWORD, NULL, -1, OBJNULL}, diff --git a/src/c/symbols_list2.h b/src/c/symbols_list2.h index 9bad9ff07..8e125f1d3 100644 --- a/src/c/symbols_list2.h +++ b/src/c/symbols_list2.h @@ -71,16 +71,11 @@ typedef struct { #else # define IF_SSE2(x) NULL #endif -#if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) +#if defined(HAVE_LIBFFI) # define IF_DFFI(x) x #else # define IF_DFFI(x) NULL #endif -#if defined(HAVE_LIBFFI) -# define IF_LIBFFI(x) x -#else -# define IF_LIBFFI(x) NULL -#endif cl_symbol_initializer cl_symbols[] = { @@ -1749,12 +1744,12 @@ cl_symbols[] = { {SYS_ "*CODE-WALKER*",NULL}, -/* #if defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */ +/* #if defined(HAVE_LIBFFI) */ {SYS_ "CALL-CFUN",IF_DFFI("si_call_cfun")}, {KEY_ "CALLBACK",NULL}, {SYS_ "MAKE-DYNAMIC-CALLBACK",IF_DFFI("si_make_dynamic_callback")}, -{SYS_ "FREE-FFI-CLOSURE",IF_LIBFFI("si_free_ffi_closure")}, -/* #endif defined(HAVE_LIBFFI) || defined(ECL_DYNAMIC_FFI) */ +{SYS_ "FREE-FFI-CLOSURE",IF_DFFI("si_free_ffi_closure")}, +/* #endif defined(HAVE_LIBFFI) */ {KEY_ "CDECL",NULL}, {KEY_ "STDCALL",NULL}, diff --git a/src/h/config.h.in b/src/h/config.h.in index 1dc3c7aba..8f87f556d 100644 --- a/src/h/config.h.in +++ b/src/h/config.h.in @@ -115,12 +115,6 @@ /* We have libffi and can use it */ #undef HAVE_LIBFFI -/* We have non-portable implementation of FFI calls */ -/* Only used as a last resort, when libffi is missin */ -#ifndef HAVE_LIBFFI -#undef ECL_DYNAMIC_FFI -#endif - /* We use hierarchical package names, like in Allegro CL */ #undef ECL_RELATIVE_PACKAGE_NAMES diff --git a/src/h/external.h b/src/h/external.h index 66d870085..c4dbbf568 100755 --- a/src/h/external.h +++ b/src/h/external.h @@ -121,9 +121,6 @@ struct cl_env_struct { union ecl_ffi_values *ffi_values; union ecl_ffi_values **ffi_values_ptrs; #endif -#ifdef ECL_DYNAMIC_FFI - void *fficall; -#endif /* Alternative stack for processing signals */ void *altstack; diff --git a/src/h/internal.h b/src/h/internal.h index a39d9187c..7f4edb0e9 100755 --- a/src/h/internal.h +++ b/src/h/internal.h @@ -244,19 +244,6 @@ struct ecl_fficall { }; extern enum ecl_ffi_tag ecl_foreign_type_code(cl_object type); -#ifdef ECL_DYNAMIC_FFI -extern enum ecl_ffi_calling_convention ecl_foreign_cc_code(cl_object cc_type); -extern void ecl_fficall_prepare(cl_object return_type, cl_object arg_types, cl_object cc_type); -extern void ecl_fficall_push_bytes(void *data, size_t bytes); -extern void ecl_fficall_push_int(int word); -extern void ecl_fficall_align(int data); - -extern struct ecl_fficall_reg *ecl_fficall_prepare_extra(struct ecl_fficall_reg *registers); -extern void ecl_fficall_push_arg(union ecl_ffi_values *data, enum ecl_ffi_tag type); -extern void ecl_fficall_execute(void *f_ptr, struct ecl_fficall *fficall, enum ecl_ffi_tag return_type); -extern void ecl_dynamic_callback_call(cl_object callback_info, char* buffer); -extern void* ecl_dynamic_callback_make(cl_object data, enum ecl_ffi_calling_convention cc_type); -#endif /* file.d */