Fix bad_abi test. rc5.

This commit is contained in:
Anthony Green
2011-02-13 08:06:39 -05:00
parent 90af15ef5c
commit 1fbf9dc44f
54 changed files with 10999 additions and 237 deletions

View File

@@ -21,3 +21,4 @@ sparc-abi-check
remove-debug-code
ungccify
ios-fixes
bad-abi-fix

View File

4529
.pc/bad-abi-fix/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,122 @@
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Copyright (C) 2007 Free Software Foundation, Inc
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
#ifndef FFI_COMMON_H
#define FFI_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <fficonfig.h>
/* Do not move this. Some versions of AIX are very picky about where
this is positioned. */
#ifdef __GNUC__
/* mingw64 defines this already in malloc.h. */
#ifndef alloca
# define alloca __builtin_alloca
#endif
# define MAYBE_UNUSED __attribute__((__unused__))
#else
# define MAYBE_UNUSED
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
# ifdef _MSC_VER
# define alloca _alloca
# else
char *alloca ();
# endif
# endif
# endif
# endif
#endif
/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#if defined(FFI_DEBUG)
#include <stdio.h>
#endif
#ifdef FFI_DEBUG
void ffi_assert(char *expr, char *file, int line);
void ffi_stop_here(void);
void ffi_type_test(ffi_type *a, char *file, int line);
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
#endif
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
/* Extended cif, used in callback from assembly routine */
typedef struct
{
ffi_cif *cif;
void *rvalue;
void **avalue;
} extended_cif;
/* Terse sized type definitions. */
#if defined(_MSC_VER) || defined(__sgi)
typedef unsigned char UINT8;
typedef signed char SINT8;
typedef unsigned short UINT16;
typedef signed short SINT16;
typedef unsigned int UINT32;
typedef signed int SINT32;
# ifdef _MSC_VER
typedef unsigned __int64 UINT64;
typedef signed __int64 SINT64;
# else
# include <inttypes.h>
typedef uint64_t UINT64;
typedef int64_t SINT64;
# endif
#else
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
#endif
typedef float FLOAT32;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,722 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
/* Forward declares. */
static int vfp_type_p (ffi_type *);
static void layout_vfp_args (ffi_cif *);
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments
The vfp_space parameter is the load area for VFP regs, the return
value is cif->vfp_used (word bitset of VFP regs used for passing
arguments). These are only used for the VFP hard-float ABI.
*/
int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
{
register unsigned int i, vi = 0;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
*(void **) argp = ecif->rvalue;
argp += 4;
}
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0);
i--, p_arg++)
{
size_t z;
/* Allocated in VFP registers. */
if (ecif->cif->abi == FFI_VFP
&& vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
{
float* vfp_slot = vfp_space + ecif->cif->vfp_args[vi++];
if ((*p_arg)->type == FFI_TYPE_FLOAT)
*((float*)vfp_slot) = *((float*)*p_argv);
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
*((double*)vfp_slot) = *((double*)*p_argv);
else
memcpy(vfp_slot, *p_argv, (*p_arg)->size);
p_argv++;
continue;
}
/* Align if necessary */
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
}
if ((*p_arg)->type == FFI_TYPE_STRUCT)
argp = (char *) ALIGN(argp, 4);
z = (*p_arg)->size;
if (z < sizeof(int))
{
z = sizeof(int);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
break;
case FFI_TYPE_STRUCT:
memcpy(argp, *p_argv, (*p_arg)->size);
break;
default:
FFI_ASSERT(0);
}
}
else if (z == sizeof(int))
{
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
}
else
{
memcpy(argp, *p_argv, z);
}
p_argv++;
argp += z;
}
/* Indicate the VFP registers used. */
return ecif->cif->vfp_used;
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
int type_code;
/* Round the stack up to a multiple of 8 bytes. This isn't needed
everywhere, but it is on some platforms, and it doesn't harm anything
when it isn't needed. */
cif->bytes = (cif->bytes + 7) & ~7;
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
cif->flags = (unsigned) cif->rtype->type;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = (unsigned) FFI_TYPE_SINT64;
break;
case FFI_TYPE_STRUCT:
if (cif->abi == FFI_VFP
&& (type_code = vfp_type_p (cif->rtype)) != 0)
{
/* A Composite Type passed in VFP registers, either
FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
cif->flags = (unsigned) type_code;
}
else if (cif->rtype->size <= 4)
/* A Composite Type not larger than 4 bytes is returned in r0. */
cif->flags = (unsigned)FFI_TYPE_INT;
else
/* A Composite Type larger than 4 bytes, or whose size cannot
be determined statically ... is stored in memory at an
address passed [in r0]. */
cif->flags = (unsigned)FFI_TYPE_STRUCT;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
}
/* Map out the register placements of VFP register args.
The VFP hard-float calling conventions are slightly more sophisticated than
the base calling conventions, so we do it here instead of in ffi_prep_args(). */
if (cif->abi == FFI_VFP)
layout_vfp_args (cif);
return FFI_OK;
}
/* Prototypes for assembly functions, in sysv.S */
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
int small_struct = (cif->flags == FFI_TYPE_INT
&& cif->rtype->type == FFI_TYPE_STRUCT);
int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
|| cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
ecif.cif = cif;
ecif.avalue = avalue;
unsigned int temp;
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
if ((rvalue == NULL) &&
(cif->flags == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
}
else if (small_struct)
ecif.rvalue = &temp;
else if (vfp_struct)
{
/* Largest case is double x 4. */
ecif.rvalue = alloca(32);
}
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
break;
case FFI_VFP:
ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
break;
default:
FFI_ASSERT(0);
break;
}
if (small_struct)
memcpy (rvalue, &temp, cif->rtype->size);
else if (vfp_struct)
memcpy (rvalue, ecif.rvalue, cif->rtype->size);
}
/** private members **/
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
void** args, ffi_cif* cif, float *vfp_stack);
void ffi_closure_SYSV (ffi_closure *);
void ffi_closure_VFP (ffi_closure *);
/* This function is jumped to by the trampoline */
unsigned int
ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
ffi_closure *closure;
void **respp;
void *args;
void *vfp_args;
{
// our various things...
ffi_cif *cif;
void **arg_area;
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
/* this call will initialize ARG_AREA, such that each
* element in that array points to the corresponding
* value on the stack; and if the function returns
* a structure, it will re-set RESP to point to the
* structure return address. */
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
(closure->fun) (cif, *respp, arg_area, closure->user_data);
return cif->flags;
}
/*@-exportheader@*/
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif,
/* Used only under VFP hard-float ABI. */
float *vfp_stack)
/*@=exportheader@*/
{
register unsigned int i, vi = 0;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if ( cif->flags == FFI_TYPE_STRUCT ) {
*rvalue = *(void **) argp;
argp += 4;
}
p_argv = avalue;
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
{
size_t z;
size_t alignment;
if (cif->abi == FFI_VFP
&& vi < cif->vfp_nargs && vfp_type_p (*p_arg))
{
*p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
continue;
}
alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
/* Align if necessary */
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, alignment);
}
z = (*p_arg)->size;
/* because we're little endian, this is what it turns into. */
*p_argv = (void*) argp;
p_argv++;
argp += z;
}
return;
}
/* How to make a trampoline. */
#if FFI_EXEC_TRAMPOLINE_TABLE
#include <mach/mach.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
extern void *ffi_closure_trampoline_table_page;
typedef struct ffi_trampoline_table ffi_trampoline_table;
typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
struct ffi_trampoline_table {
/* contigious writable and executable pages */
vm_address_t config_page;
vm_address_t trampoline_page;
/* free list tracking */
uint16_t free_count;
ffi_trampoline_table_entry *free_list;
ffi_trampoline_table_entry *free_list_pool;
ffi_trampoline_table *prev;
ffi_trampoline_table *next;
};
struct ffi_trampoline_table_entry {
void *(*trampoline)();
ffi_trampoline_table_entry *next;
};
/* Override the standard architecture trampoline size */
// XXX TODO - Fix
#undef FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE 12
/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
/* Total number of trampolines that fit in one trampoline table */
#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
static ffi_trampoline_table *ffi_trampoline_tables = NULL;
static ffi_trampoline_table *
ffi_trampoline_table_alloc ()
{
ffi_trampoline_table *table = NULL;
/* Loop until we can allocate two contigious pages */
while (table == NULL) {
vm_address_t config_page = 0x0;
kern_return_t kt;
/* Try to allocate two pages */
kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
if (kt != KERN_SUCCESS) {
fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
break;
}
/* Now drop the second half of the allocation to make room for the trampoline table */
vm_address_t trampoline_page = config_page+PAGE_SIZE;
kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
if (kt != KERN_SUCCESS) {
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
break;
}
/* Remap the trampoline table to directly follow the config page */
vm_prot_t cur_prot;
vm_prot_t max_prot;
kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
/* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
if (kt != KERN_SUCCESS) {
/* Log unexpected failures */
if (kt != KERN_NO_SPACE) {
fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
}
vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
continue;
}
/* We have valid trampoline and config pages */
table = calloc (1, sizeof(ffi_trampoline_table));
table->free_count = FFI_TRAMPOLINE_COUNT;
table->config_page = config_page;
table->trampoline_page = trampoline_page;
/* Create and initialize the free list */
table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
uint16_t i;
for (i = 0; i < table->free_count; i++) {
ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
if (i < table->free_count - 1)
entry->next = &table->free_list_pool[i+1];
}
table->free_list = table->free_list_pool;
}
return table;
}
void *
ffi_closure_alloc (size_t size, void **code)
{
/* Create the closure */
ffi_closure *closure = malloc(size);
if (closure == NULL)
return NULL;
pthread_mutex_lock(&ffi_trampoline_lock);
/* Check for an active trampoline table with available entries. */
ffi_trampoline_table *table = ffi_trampoline_tables;
if (table == NULL || table->free_list == NULL) {
table = ffi_trampoline_table_alloc ();
if (table == NULL) {
free(closure);
return NULL;
}
/* Insert the new table at the top of the list */
table->next = ffi_trampoline_tables;
if (table->next != NULL)
table->next->prev = table;
ffi_trampoline_tables = table;
}
/* Claim the free entry */
ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
ffi_trampoline_tables->free_list = entry->next;
ffi_trampoline_tables->free_count--;
entry->next = NULL;
pthread_mutex_unlock(&ffi_trampoline_lock);
/* Initialize the return values */
*code = entry->trampoline;
closure->trampoline_table = table;
closure->trampoline_table_entry = entry;
return closure;
}
void
ffi_closure_free (void *ptr)
{
ffi_closure *closure = ptr;
pthread_mutex_lock(&ffi_trampoline_lock);
/* Fetch the table and entry references */
ffi_trampoline_table *table = closure->trampoline_table;
ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
/* Return the entry to the free list */
entry->next = table->free_list;
table->free_list = entry;
table->free_count++;
/* If all trampolines within this table are free, and at least one other table exists, deallocate
* the table */
if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
/* Remove from the list */
if (table->prev != NULL)
table->prev->next = table->next;
if (table->next != NULL)
table->next->prev = table->prev;
/* Deallocate pages */
kern_return_t kt;
kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
/* Deallocate free list */
free (table->free_list_pool);
free (table);
} else if (ffi_trampoline_tables != table) {
/* Otherwise, bump this table to the top of the list */
table->prev = NULL;
table->next = ffi_trampoline_tables;
if (ffi_trampoline_tables != NULL)
ffi_trampoline_tables->prev = table;
ffi_trampoline_tables = table;
}
pthread_mutex_unlock (&ffi_trampoline_lock);
/* Free the closure */
free (closure);
}
#else
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
*(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \
*(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
*(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
*(unsigned int*) &__tramp[12] = __ctx; \
*(unsigned int*) &__tramp[16] = __fun; \
__clear_cache((&__tramp[0]), (&__tramp[19])); \
})
#endif
/* the cif must already be prep'ed */
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
void (*closure_func)(ffi_closure*) = NULL;
if (cif->abi == FFI_SYSV)
closure_func = &ffi_closure_SYSV;
else if (cif->abi == FFI_VFP)
closure_func = &ffi_closure_VFP;
else
FFI_ASSERT (0);
#if FFI_EXEC_TRAMPOLINE_TABLE
void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
config[0] = closure;
config[1] = closure_func;
#else
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
closure_func, \
codeloc);
#endif
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
/* Below are routines for VFP hard-float support. */
static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
{
switch (t->type)
{
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
*elt = (int) t->type;
*elnum = 1;
return 1;
case FFI_TYPE_STRUCT_VFP_FLOAT:
*elt = FFI_TYPE_FLOAT;
*elnum = t->size / sizeof (float);
return 1;
case FFI_TYPE_STRUCT_VFP_DOUBLE:
*elt = FFI_TYPE_DOUBLE;
*elnum = t->size / sizeof (double);
return 1;
case FFI_TYPE_STRUCT:;
{
int base_elt = 0, total_elnum = 0;
ffi_type **el = t->elements;
while (*el)
{
int el_elt = 0, el_elnum = 0;
if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
|| (base_elt && base_elt != el_elt)
|| total_elnum + el_elnum > 4)
return 0;
base_elt = el_elt;
total_elnum += el_elnum;
el++;
}
*elnum = total_elnum;
*elt = base_elt;
return 1;
}
default: ;
}
return 0;
}
static int vfp_type_p (ffi_type *t)
{
int elt, elnum;
if (rec_vfp_type_p (t, &elt, &elnum))
{
if (t->type == FFI_TYPE_STRUCT)
{
if (elnum == 1)
t->type = elt;
else
t->type = (elt == FFI_TYPE_FLOAT
? FFI_TYPE_STRUCT_VFP_FLOAT
: FFI_TYPE_STRUCT_VFP_DOUBLE);
}
return (int) t->type;
}
return 0;
}
static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
{
int reg = cif->vfp_reg_free;
int nregs = t->size / sizeof (float);
int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
|| t->type == FFI_TYPE_FLOAT) ? 1 : 2);
/* Align register number. */
if ((reg & 1) && align == 2)
reg++;
while (reg + nregs <= 16)
{
int s, new_used = 0;
for (s = reg; s < reg + nregs; s++)
{
new_used |= (1 << s);
if (cif->vfp_used & (1 << s))
{
reg += align;
goto next_reg;
}
}
/* Found regs to allocate. */
cif->vfp_used |= new_used;
cif->vfp_args[cif->vfp_nargs++] = reg;
/* Update vfp_reg_free. */
if (cif->vfp_used & (1 << cif->vfp_reg_free))
{
reg += nregs;
while (cif->vfp_used & (1 << reg))
reg += 1;
cif->vfp_reg_free = reg;
}
return;
next_reg: ;
}
}
static void layout_vfp_args (ffi_cif *cif)
{
int i;
/* Init VFP fields */
cif->vfp_used = 0;
cif->vfp_nargs = 0;
cif->vfp_reg_free = 0;
memset (cif->vfp_args, -1, 16); /* Init to -1. */
for (i = 0; i < cif->nargs; i++)
{
ffi_type *t = cif->arg_types[i];
if (vfp_type_p (t))
place_vfp_arg (cif, t);
}
}

View File

@@ -0,0 +1,421 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
AVR32 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <asm/unistd.h>
/* #define DEBUG */
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned int, unsigned int, unsigned int*, unsigned int,
void (*fn)(void));
extern void ffi_closure_SYSV (ffi_closure *);
unsigned int pass_struct_on_stack(ffi_type *type)
{
if(type->type != FFI_TYPE_STRUCT)
return 0;
if(type->alignment < type->size &&
!(type->size == 4 || type->size == 8) &&
!(type->size == 8 && type->alignment >= 4))
return 1;
if(type->size == 3 || type->size == 5 || type->size == 6 ||
type->size == 7)
return 1;
return 0;
}
/* ffi_prep_args is called by the assembly routine once stack space
* has been allocated for the function's arguments
*
* This is annoyingly complex since we need to keep track of used
* registers.
*/
void ffi_prep_args(char *stack, extended_cif *ecif)
{
unsigned int i;
void **p_argv;
ffi_type **p_arg;
char *reg_base = stack;
char *stack_base = stack + 20;
unsigned int stack_offset = 0;
unsigned int reg_mask = 0;
p_argv = ecif->avalue;
/* If cif->flags is struct then we know it's not passed in registers */
if(ecif->cif->flags == FFI_TYPE_STRUCT)
{
*(void**)reg_base = ecif->rvalue;
reg_mask |= 1;
}
for(i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
i++, p_arg++)
{
size_t z = (*p_arg)->size;
int alignment = (*p_arg)->alignment;
int type = (*p_arg)->type;
char *addr = 0;
if(z % 4 != 0)
z += (4 - z % 4);
if(reg_mask != 0x1f)
{
if(pass_struct_on_stack(*p_arg))
{
addr = stack_base + stack_offset;
stack_offset += z;
}
else if(z == sizeof(int))
{
char index = 0;
while((reg_mask >> index) & 1)
index++;
addr = reg_base + (index * 4);
reg_mask |= (1 << index);
}
else if(z == 2 * sizeof(int))
{
if(!((reg_mask >> 1) & 1))
{
addr = reg_base + 4;
reg_mask |= (3 << 1);
}
else if(!((reg_mask >> 3) & 1))
{
addr = reg_base + 12;
reg_mask |= (3 << 3);
}
}
}
if(!addr)
{
addr = stack_base + stack_offset;
stack_offset += z;
}
if(type == FFI_TYPE_STRUCT && (*p_arg)->elements[1] == NULL)
type = (*p_arg)->elements[0]->type;
switch(type)
{
case FFI_TYPE_UINT8:
*(unsigned int *)addr = (unsigned int)*(UINT8 *)(*p_argv);
break;
case FFI_TYPE_SINT8:
*(signed int *)addr = (signed int)*(SINT8 *)(*p_argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *)addr = (unsigned int)*(UINT16 *)(*p_argv);
break;
case FFI_TYPE_SINT16:
*(signed int *)addr = (signed int)*(SINT16 *)(*p_argv);
break;
default:
memcpy(addr, *p_argv, z);
}
p_argv++;
}
#ifdef DEBUG
/* Debugging */
for(i = 0; i < 5; i++)
{
if((reg_mask & (1 << i)) == 0)
printf("r%d: (unused)\n", 12 - i);
else
printf("r%d: 0x%08x\n", 12 - i, ((unsigned int*)reg_base)[i]);
}
for(i = 0; i < stack_offset / 4; i++)
{
printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack_base)[i]);
}
#endif
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
/* Round the stack up to a multiple of 8 bytes. This isn't needed
* everywhere, but it is on some platforms, and it doesn't harm
* anything when it isn't needed. */
cif->bytes = (cif->bytes + 7) & ~7;
/* Flag to indicate that he return value is in fact a struct */
cif->rstruct_flag = 0;
/* Set the return type flag */
switch(cif->rtype->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
cif->flags = (unsigned)FFI_TYPE_UINT8;
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
cif->flags = (unsigned)FFI_TYPE_UINT16;
break;
case FFI_TYPE_FLOAT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
cif->flags = (unsigned)FFI_TYPE_UINT32;
break;
case FFI_TYPE_DOUBLE:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = (unsigned)FFI_TYPE_UINT64;
break;
case FFI_TYPE_STRUCT:
cif->rstruct_flag = 1;
if(!pass_struct_on_stack(cif->rtype))
{
if(cif->rtype->size <= 1)
cif->flags = (unsigned)FFI_TYPE_UINT8;
else if(cif->rtype->size <= 2)
cif->flags = (unsigned)FFI_TYPE_UINT16;
else if(cif->rtype->size <= 4)
cif->flags = (unsigned)FFI_TYPE_UINT32;
else if(cif->rtype->size <= 8)
cif->flags = (unsigned)FFI_TYPE_UINT64;
else
cif->flags = (unsigned)cif->rtype->type;
}
else
cif->flags = (unsigned)cif->rtype->type;
break;
default:
cif->flags = (unsigned)cif->rtype->type;
break;
}
return FFI_OK;
}
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
unsigned int size = 0, i = 0;
ffi_type **p_arg;
ecif.cif = cif;
ecif.avalue = avalue;
for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
size += (*p_arg)->size + (4 - (*p_arg)->size % 4);
/* If the return value is a struct and we don't have a return value
* address then we need to make one */
/* If cif->flags is struct then it's not suitable for registers */
if((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT))
ecif.rvalue = alloca(cif->rtype->size);
else
ecif.rvalue = rvalue;
switch(cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, size, cif->flags,
ecif.rvalue, cif->rstruct_flag, fn);
break;
default:
FFI_ASSERT(0);
break;
}
}
static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif)
{
register unsigned int i, reg_mask = 0;
register void **p_argv;
register ffi_type **p_arg;
register char *reg_base = stack;
register char *stack_base = stack + 20;
register unsigned int stack_offset = 0;
#ifdef DEBUG
/* Debugging */
for(i = 0; i < cif->nargs + 7; i++)
{
printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack)[i]);
}
#endif
/* If cif->flags is struct then we know it's not passed in registers */
if(cif->flags == FFI_TYPE_STRUCT)
{
*rvalue = *(void **)reg_base;
reg_mask |= 1;
}
p_argv = avalue;
for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
{
size_t z = (*p_arg)->size;
int alignment = (*p_arg)->alignment;
*p_argv = 0;
if(z % 4 != 0)
z += (4 - z % 4);
if(reg_mask != 0x1f)
{
if(pass_struct_on_stack(*p_arg))
{
*p_argv = (void*)stack_base + stack_offset;
stack_offset += z;
}
else if(z <= sizeof(int))
{
char index = 0;
while((reg_mask >> index) & 1)
index++;
*p_argv = (void*)reg_base + (index * 4);
reg_mask |= (1 << index);
}
else if(z == 2 * sizeof(int))
{
if(!((reg_mask >> 1) & 1))
{
*p_argv = (void*)reg_base + 4;
reg_mask |= (3 << 1);
}
else if(!((reg_mask >> 3) & 1))
{
*p_argv = (void*)reg_base + 12;
reg_mask |= (3 << 3);
}
}
}
if(!*p_argv)
{
*p_argv = (void*)stack_base + stack_offset;
stack_offset += z;
}
if((*p_arg)->type != FFI_TYPE_STRUCT ||
(*p_arg)->elements[1] == NULL)
{
if(alignment == 1)
**(unsigned int**)p_argv <<= 24;
else if(alignment == 2)
**(unsigned int**)p_argv <<= 16;
}
p_argv++;
}
#ifdef DEBUG
/* Debugging */
for(i = 0; i < cif->nargs; i++)
{
printf("sp+%d: 0x%08x\n", i*4, *(((unsigned int**)avalue)[i]));
}
#endif
}
/* This function is jumped to by the trampoline */
unsigned int ffi_closure_SYSV_inner(ffi_closure *closure, void **respp,
void *args)
{
ffi_cif *cif;
void **arg_area;
unsigned int i, size = 0;
ffi_type **p_arg;
cif = closure->cif;
for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
size += (*p_arg)->size + (4 - (*p_arg)->size % 4);
arg_area = (void **)alloca(size);
/* this call will initialize ARG_AREA, such that each element in that
* array points to the corresponding value on the stack; and if the
* function returns a structure, it will re-set RESP to point to the
* structure return address. */
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
(closure->fun)(cif, *respp, arg_area, closure->user_data);
return cif->flags;
}
ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
void *codeloc)
{
FFI_ASSERT(cif->abi == FFI_SYSV);
unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);
unsigned int __ctx = (unsigned int)(codeloc);
unsigned int __rstruct_flag = (unsigned int)(cif->rstruct_flag);
unsigned int __inner = (unsigned int)(&ffi_closure_SYSV_inner);
*(unsigned int*) &__tramp[0] = 0xebcd1f00; /* pushm r8-r12 */
*(unsigned int*) &__tramp[4] = 0xfefc0010; /* ld.w r12, pc[16] */
*(unsigned int*) &__tramp[8] = 0xfefb0010; /* ld.w r11, pc[16] */
*(unsigned int*) &__tramp[12] = 0xfefa0010; /* ld.w r10, pc[16] */
*(unsigned int*) &__tramp[16] = 0xfeff0010; /* ld.w pc, pc[16] */
*(unsigned int*) &__tramp[20] = __ctx;
*(unsigned int*) &__tramp[24] = __rstruct_flag;
*(unsigned int*) &__tramp[28] = __inner;
*(unsigned int*) &__tramp[32] = __fun;
syscall(__NR_cacheflush, 0, (&__tramp[0]), 36);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}

View File

@@ -0,0 +1,580 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
Copyright (c) 2000 Hewlett Packard Company
IA64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdbool.h>
#include <float.h>
#include "ia64_flags.h"
/* A 64-bit pointer value. In LP64 mode, this is effectively a plain
pointer. In ILP32 mode, it's a pointer that's been extended to
64 bits by "addp4". */
typedef void *PTR64 __attribute__((mode(DI)));
/* Memory image of fp register contents. This is the implementation
specific format used by ldf.fill/stf.spill. All we care about is
that it wants a 16 byte aligned slot. */
typedef struct
{
UINT64 x[2] __attribute__((aligned(16)));
} fpreg;
/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */
struct ia64_args
{
fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */
UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */
UINT64 other_args[]; /* Arguments passed on stack, variable size. */
};
/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */
static inline void *
endian_adjust (void *addr, size_t len)
{
#ifdef __BIG_ENDIAN__
return addr + (8 - len);
#else
return addr;
#endif
}
/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
This is a macro instead of a function, so that it works for all 3 floating
point types without type conversions. Type conversion to long double breaks
the denorm support. */
#define stf_spill(addr, value) \
asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
/* Load a value from ADDR, which is in the current cpu implementation's
fp spill format. As above, this must also be a macro. */
#define ldf_fill(result, addr) \
asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
/* Return the size of the C type associated with with TYPE. Which will
be one of the FFI_IA64_TYPE_HFA_* values. */
static size_t
hfa_type_size (int type)
{
switch (type)
{
case FFI_IA64_TYPE_HFA_FLOAT:
return sizeof(float);
case FFI_IA64_TYPE_HFA_DOUBLE:
return sizeof(double);
case FFI_IA64_TYPE_HFA_LDOUBLE:
return sizeof(__float80);
default:
abort ();
}
}
/* Load from ADDR a value indicated by TYPE. Which will be one of
the FFI_IA64_TYPE_HFA_* values. */
static void
hfa_type_load (fpreg *fpaddr, int type, void *addr)
{
switch (type)
{
case FFI_IA64_TYPE_HFA_FLOAT:
stf_spill (fpaddr, *(float *) addr);
return;
case FFI_IA64_TYPE_HFA_DOUBLE:
stf_spill (fpaddr, *(double *) addr);
return;
case FFI_IA64_TYPE_HFA_LDOUBLE:
stf_spill (fpaddr, *(__float80 *) addr);
return;
default:
abort ();
}
}
/* Load VALUE into ADDR as indicated by TYPE. Which will be one of
the FFI_IA64_TYPE_HFA_* values. */
static void
hfa_type_store (int type, void *addr, fpreg *fpaddr)
{
switch (type)
{
case FFI_IA64_TYPE_HFA_FLOAT:
{
float result;
ldf_fill (result, fpaddr);
*(float *) addr = result;
break;
}
case FFI_IA64_TYPE_HFA_DOUBLE:
{
double result;
ldf_fill (result, fpaddr);
*(double *) addr = result;
break;
}
case FFI_IA64_TYPE_HFA_LDOUBLE:
{
__float80 result;
ldf_fill (result, fpaddr);
*(__float80 *) addr = result;
break;
}
default:
abort ();
}
}
/* Is TYPE a struct containing floats, doubles, or extended doubles,
all of the same fp type? If so, return the element type. Return
FFI_TYPE_VOID if not. */
static int
hfa_element_type (ffi_type *type, int nested)
{
int element = FFI_TYPE_VOID;
switch (type->type)
{
case FFI_TYPE_FLOAT:
/* We want to return VOID for raw floating-point types, but the
synthetic HFA type if we're nested within an aggregate. */
if (nested)
element = FFI_IA64_TYPE_HFA_FLOAT;
break;
case FFI_TYPE_DOUBLE:
/* Similarly. */
if (nested)
element = FFI_IA64_TYPE_HFA_DOUBLE;
break;
case FFI_TYPE_LONGDOUBLE:
/* Similarly, except that that HFA is true for double extended,
but not quad precision. Both have sizeof == 16, so tell the
difference based on the precision. */
if (LDBL_MANT_DIG == 64 && nested)
element = FFI_IA64_TYPE_HFA_LDOUBLE;
break;
case FFI_TYPE_STRUCT:
{
ffi_type **ptr = &type->elements[0];
for (ptr = &type->elements[0]; *ptr ; ptr++)
{
int sub_element = hfa_element_type (*ptr, 1);
if (sub_element == FFI_TYPE_VOID)
return FFI_TYPE_VOID;
if (element == FFI_TYPE_VOID)
element = sub_element;
else if (element != sub_element)
return FFI_TYPE_VOID;
}
}
break;
default:
return FFI_TYPE_VOID;
}
return element;
}
/* Perform machine dependent cif processing. */
ffi_status
ffi_prep_cif_machdep(ffi_cif *cif)
{
int flags;
/* Adjust cif->bytes to include space for the bits of the ia64_args frame
that precedes the integer register portion. The estimate that the
generic bits did for the argument space required is good enough for the
integer component. */
cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
if (cif->bytes < sizeof(struct ia64_args))
cif->bytes = sizeof(struct ia64_args);
/* Set the return type flag. */
flags = cif->rtype->type;
switch (cif->rtype->type)
{
case FFI_TYPE_LONGDOUBLE:
/* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
and encode quad precision as a two-word integer structure. */
if (LDBL_MANT_DIG != 64)
flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
break;
case FFI_TYPE_STRUCT:
{
size_t size = cif->rtype->size;
int hfa_type = hfa_element_type (cif->rtype, 0);
if (hfa_type != FFI_TYPE_VOID)
{
size_t nelts = size / hfa_type_size (hfa_type);
if (nelts <= 8)
flags = hfa_type | (size << 8);
}
else
{
if (size <= 32)
flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
}
}
break;
default:
break;
}
cif->flags = flags;
return FFI_OK;
}
extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
struct ia64_args *stack;
long i, avn, gpcount, fpcount;
ffi_type **p_arg;
FFI_ASSERT (cif->abi == FFI_UNIX);
/* If we have no spot for a return value, make one. */
if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
rvalue = alloca (cif->rtype->size);
/* Allocate the stack frame. */
stack = alloca (cif->bytes);
gpcount = fpcount = 0;
avn = cif->nargs;
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
{
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
break;
case FFI_TYPE_UINT8:
stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
break;
case FFI_TYPE_SINT16:
stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
break;
case FFI_TYPE_UINT16:
stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
break;
case FFI_TYPE_SINT32:
stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
break;
case FFI_TYPE_UINT32:
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
break;
case FFI_TYPE_POINTER:
stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
break;
case FFI_TYPE_FLOAT:
if (gpcount < 8 && fpcount < 8)
stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
break;
case FFI_TYPE_DOUBLE:
if (gpcount < 8 && fpcount < 8)
stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
break;
case FFI_TYPE_LONGDOUBLE:
if (gpcount & 1)
gpcount++;
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
gpcount += 2;
break;
case FFI_TYPE_STRUCT:
{
size_t size = (*p_arg)->size;
size_t align = (*p_arg)->alignment;
int hfa_type = hfa_element_type (*p_arg, 0);
FFI_ASSERT (align <= 16);
if (align == 16 && (gpcount & 1))
gpcount++;
if (hfa_type != FFI_TYPE_VOID)
{
size_t hfa_size = hfa_type_size (hfa_type);
size_t offset = 0;
size_t gp_offset = gpcount * 8;
while (fpcount < 8
&& offset < size
&& gp_offset < 8 * 8)
{
hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
avalue[i] + offset);
offset += hfa_size;
gp_offset += hfa_size;
fpcount += 1;
}
}
memcpy (&stack->gp_regs[gpcount], avalue[i], size);
gpcount += (size + 7) / 8;
}
break;
default:
abort ();
}
}
ffi_call_unix (stack, rvalue, fn, cif->flags);
}
/* Closures represent a pair consisting of a function pointer, and
some user data. A closure is invoked by reinterpreting the closure
as a function pointer, and branching to it. Thus we can make an
interpreted function callable as a C function: We turn the
interpreter itself, together with a pointer specifying the
interpreted procedure, into a closure.
For IA64, function pointer are already pairs consisting of a code
pointer, and a gp pointer. The latter is needed to access global
variables. Here we set up such a pair as the first two words of
the closure (in the "trampoline" area), but we replace the gp
pointer with a pointer to the closure itself. We also add the real
gp pointer to the closure. This allows the function entry code to
both retrieve the user data, and to restire the correct gp pointer. */
extern void ffi_closure_unix ();
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
/* The layout of a function descriptor. A C function pointer really
points to one of these. */
struct ia64_fd
{
UINT64 code_pointer;
UINT64 gp;
};
struct ffi_ia64_trampoline_struct
{
UINT64 code_pointer; /* Pointer to ffi_closure_unix. */
UINT64 fake_gp; /* Pointer to closure, installed as gp. */
UINT64 real_gp; /* Real gp value. */
};
struct ffi_ia64_trampoline_struct *tramp;
struct ia64_fd *fd;
FFI_ASSERT (cif->abi == FFI_UNIX);
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
fd = (struct ia64_fd *)(void *)ffi_closure_unix;
tramp->code_pointer = fd->code_pointer;
tramp->real_gp = fd->gp;
tramp->fake_gp = (UINT64)(PTR64)codeloc;
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
UINT64
ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
void *rvalue, void *r8)
{
ffi_cif *cif;
void **avalue;
ffi_type **p_arg;
long i, avn, gpcount, fpcount;
cif = closure->cif;
avn = cif->nargs;
avalue = alloca (avn * sizeof (void *));
/* If the structure return value is passed in memory get that location
from r8 so as to pass the value directly back to the caller. */
if (cif->flags == FFI_TYPE_STRUCT)
rvalue = r8;
gpcount = fpcount = 0;
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
{
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
avalue[i] = &stack->gp_regs[gpcount++];
break;
case FFI_TYPE_POINTER:
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
break;
case FFI_TYPE_FLOAT:
if (gpcount < 8 && fpcount < 8)
{
fpreg *addr = &stack->fp_regs[fpcount++];
float result;
avalue[i] = addr;
ldf_fill (result, addr);
*(float *)addr = result;
}
else
avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
gpcount++;
break;
case FFI_TYPE_DOUBLE:
if (gpcount < 8 && fpcount < 8)
{
fpreg *addr = &stack->fp_regs[fpcount++];
double result;
avalue[i] = addr;
ldf_fill (result, addr);
*(double *)addr = result;
}
else
avalue[i] = &stack->gp_regs[gpcount];
gpcount++;
break;
case FFI_TYPE_LONGDOUBLE:
if (gpcount & 1)
gpcount++;
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
{
fpreg *addr = &stack->fp_regs[fpcount++];
__float80 result;
avalue[i] = addr;
ldf_fill (result, addr);
*(__float80 *)addr = result;
}
else
avalue[i] = &stack->gp_regs[gpcount];
gpcount += 2;
break;
case FFI_TYPE_STRUCT:
{
size_t size = (*p_arg)->size;
size_t align = (*p_arg)->alignment;
int hfa_type = hfa_element_type (*p_arg, 0);
FFI_ASSERT (align <= 16);
if (align == 16 && (gpcount & 1))
gpcount++;
if (hfa_type != FFI_TYPE_VOID)
{
size_t hfa_size = hfa_type_size (hfa_type);
size_t offset = 0;
size_t gp_offset = gpcount * 8;
void *addr = alloca (size);
avalue[i] = addr;
while (fpcount < 8
&& offset < size
&& gp_offset < 8 * 8)
{
hfa_type_store (hfa_type, addr + offset,
&stack->fp_regs[fpcount]);
offset += hfa_size;
gp_offset += hfa_size;
fpcount += 1;
}
if (offset < size)
memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
size - offset);
}
else
avalue[i] = &stack->gp_regs[gpcount];
gpcount += (size + 7) / 8;
}
break;
default:
abort ();
}
}
closure->fun (cif, rvalue, avalue, closure->user_data);
return cif->flags;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,716 @@
/* -----------------------------------------------------------------------
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
(c) 2008 Red Hat, Inc.
HPPA Foreign Function Interface
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdio.h>
#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
#define MIN_STACK_SIZE 64
#define FIRST_ARG_SLOT 9
#define DEBUG_LEVEL 0
#define fldw(addr, fpreg) \
__asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
#define fstw(fpreg, addr) \
__asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define fldd(addr, fpreg) \
__asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
#define fstd(fpreg, addr) \
__asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
static inline int ffi_struct_type(ffi_type *t)
{
size_t sz = t->size;
/* Small structure results are passed in registers,
larger ones are passed by pointer. Note that
small structures of size 2, 4 and 8 differ from
the corresponding integer types in that they have
different alignment requirements. */
if (sz <= 1)
return FFI_TYPE_UINT8;
else if (sz == 2)
return FFI_TYPE_SMALL_STRUCT2;
else if (sz == 3)
return FFI_TYPE_SMALL_STRUCT3;
else if (sz == 4)
return FFI_TYPE_SMALL_STRUCT4;
else if (sz == 5)
return FFI_TYPE_SMALL_STRUCT5;
else if (sz == 6)
return FFI_TYPE_SMALL_STRUCT6;
else if (sz == 7)
return FFI_TYPE_SMALL_STRUCT7;
else if (sz <= 8)
return FFI_TYPE_SMALL_STRUCT8;
else
return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
}
/* PA has a downward growing stack, which looks like this:
Offset
[ Variable args ]
SP = (4*(n+9)) arg word N
...
SP-52 arg word 4
[ Fixed args ]
SP-48 arg word 3
SP-44 arg word 2
SP-40 arg word 1
SP-36 arg word 0
[ Frame marker ]
...
SP-20 RP
SP-4 previous SP
The first four argument words on the stack are reserved for use by
the callee. Instead, the general and floating registers replace
the first four argument slots. Non FP arguments are passed solely
in the general registers. FP arguments are passed in both general
and floating registers when using libffi.
Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
Non-FP 64-bit args are passed in register pairs, starting
on an odd numbered register (i.e. r25+r26 and r23+r24).
FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
FP 64-bit arguments are passed in fr5 and fr7.
The registers are allocated in the same manner as stack slots.
This allows the callee to save its arguments on the stack if
necessary:
arg word 3 -> gr23 or fr7L
arg word 2 -> gr24 or fr6L or fr7R
arg word 1 -> gr25 or fr5L
arg word 0 -> gr26 or fr4L or fr5R
Note that fr4R and fr6R are never used for arguments (i.e.,
doubles are not passed in fr4 or fr6).
The rest of the arguments are passed on the stack starting at SP-52,
but 64-bit arguments need to be aligned to an 8-byte boundary
This means we can have holes either in the register allocation,
or in the stack. */
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments
The following code will put everything into the stack frame
(which was allocated by the asm routine), and on return
the asm routine will load the arguments that should be
passed by register into the appropriate registers
NOTE: We load floating point args in this function... that means we
assume gcc will not mess with fp regs in here. */
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
{
register unsigned int i;
register ffi_type **p_arg;
register void **p_argv;
unsigned int slot = FIRST_ARG_SLOT;
char *dest_cpy;
size_t len;
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
ecif, bytes);
p_arg = ecif->cif->arg_types;
p_argv = ecif->avalue;
for (i = 0; i < ecif->cif->nargs; i++)
{
int type = (*p_arg)->type;
switch (type)
{
case FFI_TYPE_SINT8:
*(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
break;
case FFI_TYPE_UINT8:
*(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
break;
case FFI_TYPE_SINT16:
*(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
break;
case FFI_TYPE_UINT16:
*(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
break;
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
slot);
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
/* Align slot for 64-bit type. */
slot += (slot & 1) ? 1 : 2;
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
break;
case FFI_TYPE_FLOAT:
/* First 4 args go in fr4L - fr7L. */
debug(3, "Storing UINT32(float) in slot %u\n", slot);
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
switch (slot - FIRST_ARG_SLOT)
{
/* First 4 args go in fr4L - fr7L. */
case 0: fldw(stack - slot, fr4); break;
case 1: fldw(stack - slot, fr5); break;
case 2: fldw(stack - slot, fr6); break;
case 3: fldw(stack - slot, fr7); break;
}
break;
case FFI_TYPE_DOUBLE:
/* Align slot for 64-bit type. */
slot += (slot & 1) ? 1 : 2;
debug(3, "Storing UINT64(double) at slot %u\n", slot);
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
switch (slot - FIRST_ARG_SLOT)
{
/* First 2 args go in fr5, fr7. */
case 1: fldd(stack - slot, fr5); break;
case 3: fldd(stack - slot, fr7); break;
}
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
/* Long doubles are passed in the same manner as structures
larger than 8 bytes. */
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
break;
#endif
case FFI_TYPE_STRUCT:
/* Structs smaller or equal than 4 bytes are passed in one
register. Structs smaller or equal 8 bytes are passed in two
registers. Larger structures are passed by pointer. */
len = (*p_arg)->size;
if (len <= 4)
{
dest_cpy = (char *)(stack - slot) + 4 - len;
memcpy(dest_cpy, (char *)*p_argv, len);
}
else if (len <= 8)
{
slot += (slot & 1) ? 1 : 2;
dest_cpy = (char *)(stack - slot) + 8 - len;
memcpy(dest_cpy, (char *)*p_argv, len);
}
else
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
break;
default:
FFI_ASSERT(0);
}
slot++;
p_arg++;
p_argv++;
}
/* Make sure we didn't mess up and scribble on the stack. */
{
unsigned int n;
debug(5, "Stack setup:\n");
for (n = 0; n < (bytes + 3) / 4; n++)
{
if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
debug(5, "%08x ", *(stack - n));
}
debug(5, "\n");
}
FFI_ASSERT(slot * 4 <= bytes);
return;
}
static void ffi_size_stack_pa32(ffi_cif *cif)
{
ffi_type **ptr;
int i;
int z = 0; /* # stack slots */
for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
{
int type = (*ptr)->type;
switch (type)
{
case FFI_TYPE_DOUBLE:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
z += 2 + (z & 1); /* must start on even regs, so we may waste one */
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
#endif
case FFI_TYPE_STRUCT:
z += 1; /* pass by ptr, callee will copy */
break;
default: /* <= 32-bit values */
z++;
}
}
/* We can fit up to 6 args in the default 64-byte stack frame,
if we need more, we need more stack. */
if (z <= 6)
cif->bytes = MIN_STACK_SIZE; /* min stack size */
else
cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
}
/* Perform machine dependent cif processing. */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
cif->flags = (unsigned) cif->rtype->type;
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
/* Long doubles are treated like a structure. */
cif->flags = FFI_TYPE_STRUCT;
break;
#endif
case FFI_TYPE_STRUCT:
/* For the return type we have to check the size of the structures.
If the size is smaller or equal 4 bytes, the result is given back
in one register. If the size is smaller or equal 8 bytes than we
return the result in two registers. But if the size is bigger than
8 bytes, we work with pointers. */
cif->flags = ffi_struct_type(cif->rtype);
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
cif->flags = FFI_TYPE_UINT64;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
}
/* Lucky us, because of the unique PA ABI we get to do our
own stack sizing. */
switch (cif->abi)
{
case FFI_PA32:
ffi_size_stack_pa32(cif);
break;
default:
FFI_ASSERT(0);
break;
}
return FFI_OK;
}
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
extended_cif *, unsigned, unsigned, unsigned *,
void (*fn)(void));
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
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. */
if (rvalue == NULL
#ifdef PA_HPUX
&& (cif->rtype->type == FFI_TYPE_STRUCT
|| cif->rtype->type == FFI_TYPE_LONGDOUBLE))
#else
&& cif->rtype->type == FFI_TYPE_STRUCT)
#endif
{
ecif.rvalue = alloca(cif->rtype->size);
}
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_PA32:
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
default:
FFI_ASSERT(0);
break;
}
}
#if FFI_CLOSURES
/* This is more-or-less an inverse of ffi_call -- we have arguments on
the stack, and we need to fill them into a cif structure and invoke
the user function. This really ought to be in asm to make sure
the compiler doesn't do things we don't expect. */
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
{
ffi_cif *cif;
void **avalue;
void *rvalue;
UINT32 ret[2]; /* function can return up to 64-bits in registers */
ffi_type **p_arg;
char *tmp;
int i, avn;
unsigned int slot = FIRST_ARG_SLOT;
register UINT32 r28 asm("r28");
cif = closure->cif;
/* If returning via structure, callee will write to our pointer. */
if (cif->flags == FFI_TYPE_STRUCT)
rvalue = (void *)r28;
else
rvalue = &ret[0];
avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
avn = cif->nargs;
p_arg = cif->arg_types;
for (i = 0; i < avn; i++)
{
int type = (*p_arg)->type;
switch (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_POINTER:
avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
slot += (slot & 1) ? 1 : 2;
avalue[i] = (void *)(stack - slot);
break;
case FFI_TYPE_FLOAT:
#ifdef PA_LINUX
/* The closure call is indirect. In Linux, floating point
arguments in indirect calls with a prototype are passed
in the floating point registers instead of the general
registers. So, we need to replace what was previously
stored in the current slot with the value in the
corresponding floating point register. */
switch (slot - FIRST_ARG_SLOT)
{
case 0: fstw(fr4, (void *)(stack - slot)); break;
case 1: fstw(fr5, (void *)(stack - slot)); break;
case 2: fstw(fr6, (void *)(stack - slot)); break;
case 3: fstw(fr7, (void *)(stack - slot)); break;
}
#endif
avalue[i] = (void *)(stack - slot);
break;
case FFI_TYPE_DOUBLE:
slot += (slot & 1) ? 1 : 2;
#ifdef PA_LINUX
/* See previous comment for FFI_TYPE_FLOAT. */
switch (slot - FIRST_ARG_SLOT)
{
case 1: fstd(fr5, (void *)(stack - slot)); break;
case 3: fstd(fr7, (void *)(stack - slot)); break;
}
#endif
avalue[i] = (void *)(stack - slot);
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
/* Long doubles are treated like a big structure. */
avalue[i] = (void *) *(stack - slot);
break;
#endif
case FFI_TYPE_STRUCT:
/* Structs smaller or equal than 4 bytes are passed in one
register. Structs smaller or equal 8 bytes are passed in two
registers. Larger structures are passed by pointer. */
if((*p_arg)->size <= 4)
{
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
(*p_arg)->size;
}
else if ((*p_arg)->size <= 8)
{
slot += (slot & 1) ? 1 : 2;
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
(*p_arg)->size;
}
else
avalue[i] = (void *) *(stack - slot);
break;
default:
FFI_ASSERT(0);
}
slot++;
p_arg++;
}
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data);
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
ret[1]);
/* Store the result using the lower 2 bytes of the flags. */
switch (cif->flags)
{
case FFI_TYPE_UINT8:
*(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
break;
case FFI_TYPE_SINT8:
*(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
break;
case FFI_TYPE_UINT16:
*(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
break;
case FFI_TYPE_SINT16:
*(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
*(stack - FIRST_ARG_SLOT) = ret[0];
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
*(stack - FIRST_ARG_SLOT) = ret[0];
*(stack - FIRST_ARG_SLOT - 1) = ret[1];
break;
case FFI_TYPE_DOUBLE:
fldd(rvalue, fr4);
break;
case FFI_TYPE_FLOAT:
fldw(rvalue, fr4);
break;
case FFI_TYPE_STRUCT:
/* Don't need a return value, done by caller. */
break;
case FFI_TYPE_SMALL_STRUCT2:
case FFI_TYPE_SMALL_STRUCT3:
case FFI_TYPE_SMALL_STRUCT4:
tmp = (void*)(stack - FIRST_ARG_SLOT);
tmp += 4 - cif->rtype->size;
memcpy((void*)tmp, &ret[0], cif->rtype->size);
break;
case FFI_TYPE_SMALL_STRUCT5:
case FFI_TYPE_SMALL_STRUCT6:
case FFI_TYPE_SMALL_STRUCT7:
case FFI_TYPE_SMALL_STRUCT8:
{
unsigned int ret2[2];
int off;
/* Right justify ret[0] and ret[1] */
switch (cif->flags)
{
case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
default: off = 0; break;
}
memset (ret2, 0, sizeof (ret2));
memcpy ((char *)ret2 + off, ret, 8 - off);
*(stack - FIRST_ARG_SLOT) = ret2[0];
*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
}
break;
case FFI_TYPE_POINTER:
case FFI_TYPE_VOID:
break;
default:
debug(0, "assert with cif->flags: %d\n",cif->flags);
FFI_ASSERT(0);
break;
}
return FFI_OK;
}
/* Fill in a closure to refer to the specified fun and user_data.
cif specifies the argument and result types for fun.
The cif must already be prep'ed. */
extern void ffi_closure_pa32(void);
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
UINT32 *tramp = (UINT32 *)(closure->tramp);
#ifdef PA_HPUX
UINT32 *tmp;
#endif
FFI_ASSERT (cif->abi == FFI_PA32);
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */
#ifdef PA_LINUX
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
/* Flush d/icache -- have to flush up 2 two lines because of
alignment. */
__asm__ volatile(
"fdc 0(%0)\n\t"
"fdc %1(%0)\n\t"
"fic 0(%%sr4, %0)\n\t"
"fic %1(%%sr4, %0)\n\t"
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n"
:
: "r"((unsigned long)tramp & ~31),
"r"(32 /* stride */)
: "memory");
#endif
#ifdef PA_HPUX
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
/* Flush d/icache -- have to flush three lines because of alignment. */
__asm__ volatile(
"copy %1,%0\n\t"
"fdc,m %2(%0)\n\t"
"fdc,m %2(%0)\n\t"
"fdc,m %2(%0)\n\t"
"ldsid (%1),%0\n\t"
"mtsp %0,%%sr0\n\t"
"copy %1,%0\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n"
: "=&r" ((unsigned long)tmp)
: "r" ((unsigned long)tramp & ~31),
"r" (32/* stride */)
: "memory");
#endif
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 2011 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),1)
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
/* Perform machine independent initialization of aggregate type
specifications. */
static ffi_status initialize_aggregate(ffi_type *arg)
{
ffi_type **ptr;
FFI_ASSERT(arg != NULL);
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
FFI_ASSERT(arg->alignment == 0);
ptr = &(arg->elements[0]);
if (UNLIKELY(ptr == 0))
return FFI_BAD_TYPEDEF;
while ((*ptr) != NULL)
{
if (UNLIKELY(((*ptr)->size == 0)
&& (initialize_aggregate((*ptr)) != FFI_OK)))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
ptr++;
}
/* Structure size includes tail padding. This is important for
structures that fit in one register on ABIs like the PowerPC64
Linux ABI that right justify small structs in a register.
It's also needed for nested structure layout, for example
struct A { long a; char b; }; struct B { struct A x; char y; };
should find y at an offset of 2*sizeof(long) and result in a
total size of 3*sizeof(long). */
arg->size = ALIGN (arg->size, arg->alignment);
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
else
return FFI_OK;
}
#ifndef __CRIS__
/* The CRIS ABI specifies structure elements to have byte
alignment only, so it completely overrides this functions,
which assumes "natural" alignment and padding. */
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
ffi_type *rtype, ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
return FFI_BAD_ABI;
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->rtype = rtype;
cif->flags = 0;
/* Initialize the return type if necessary */
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
/* Initialize any uninitialized aggregate type definitions */
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if !defined X86_ANY && !defined S390 && !defined PA
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_V9))
bytes += sizeof(void*);
else
#endif
{
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
cif->bytes = bytes;
/* Perform machine dependent cif processing */
return ffi_prep_cif_machdep(cif);
}
#endif /* not __CRIS__ */
#if FFI_CLOSURES
ffi_status
ffi_prep_closure (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
{
return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
}
#endif

View File

@@ -0,0 +1,640 @@
/* -----------------------------------------------------------------------
ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
Copyright (c) 2008, 2010 Red Hat, Inc.
x86-64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),1)
#include <stdlib.h>
#include <stdarg.h>
#ifdef __x86_64__
#define MAX_GPR_REGS 6
#define MAX_SSE_REGS 8
struct register_args
{
/* Registers for argument passing. */
UINT64 gpr[MAX_GPR_REGS];
__int128_t sse[MAX_SSE_REGS];
};
extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
void *raddr, void (*fnaddr)(void), unsigned ssecount);
/* All reference to register classes here is identical to the code in
gcc/config/i386/i386.c. Do *not* change one without the other. */
/* Register class used for passing given 64bit part of the argument.
These represent classes as documented by the PS ABI, with the
exception of SSESF, SSEDF classes, that are basically SSE class,
just gcc will use SF or DFmode move instead of DImode to avoid
reformatting penalties.
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
whenever possible (upper half does contain padding). */
enum x86_64_reg_class
{
X86_64_NO_CLASS,
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS,
X86_64_SSE_CLASS,
X86_64_SSESF_CLASS,
X86_64_SSEDF_CLASS,
X86_64_SSEUP_CLASS,
X86_64_X87_CLASS,
X86_64_X87UP_CLASS,
X86_64_COMPLEX_X87_CLASS,
X86_64_MEMORY_CLASS
};
#define MAX_CLASSES 4
#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
of this code is to classify each 8bytes of incoming argument by the register
class and assign registers accordingly. */
/* Return the union class of CLASS1 and CLASS2.
See the x86-64 PS ABI for details. */
static enum x86_64_reg_class
merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
{
/* Rule #1: If both classes are equal, this is the resulting class. */
if (class1 == class2)
return class1;
/* Rule #2: If one of the classes is NO_CLASS, the resulting class is
the other class. */
if (class1 == X86_64_NO_CLASS)
return class2;
if (class2 == X86_64_NO_CLASS)
return class1;
/* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
return X86_64_MEMORY_CLASS;
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
|| (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
return X86_64_INTEGERSI_CLASS;
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
return X86_64_INTEGER_CLASS;
/* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
MEMORY is used. */
if (class1 == X86_64_X87_CLASS
|| class1 == X86_64_X87UP_CLASS
|| class1 == X86_64_COMPLEX_X87_CLASS
|| class2 == X86_64_X87_CLASS
|| class2 == X86_64_X87UP_CLASS
|| class2 == X86_64_COMPLEX_X87_CLASS)
return X86_64_MEMORY_CLASS;
/* Rule #6: Otherwise class SSE is used. */
return X86_64_SSE_CLASS;
}
/* Classify the argument of type TYPE and mode MODE.
CLASSES will be filled by the register class used to pass each word
of the operand. The number of words is returned. In case the parameter
should be passed in memory, 0 is returned. As a special case for zero
sized containers, classes[0] will be NO_CLASS and 1 is returned.
See the x86-64 PS ABI for details.
*/
static int
classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
size_t byte_offset)
{
switch (type->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
{
int size = byte_offset + type->size;
if (size <= 4)
{
classes[0] = X86_64_INTEGERSI_CLASS;
return 1;
}
else if (size <= 8)
{
classes[0] = X86_64_INTEGER_CLASS;
return 1;
}
else if (size <= 12)
{
classes[0] = X86_64_INTEGER_CLASS;
classes[1] = X86_64_INTEGERSI_CLASS;
return 2;
}
else if (size <= 16)
{
classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
return 2;
}
else
FFI_ASSERT (0);
}
case FFI_TYPE_FLOAT:
if (!(byte_offset % 8))
classes[0] = X86_64_SSESF_CLASS;
else
classes[0] = X86_64_SSE_CLASS;
return 1;
case FFI_TYPE_DOUBLE:
classes[0] = X86_64_SSEDF_CLASS;
return 1;
case FFI_TYPE_LONGDOUBLE:
classes[0] = X86_64_X87_CLASS;
classes[1] = X86_64_X87UP_CLASS;
return 2;
case FFI_TYPE_STRUCT:
{
const int UNITS_PER_WORD = 8;
int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
ffi_type **ptr;
int i;
enum x86_64_reg_class subclasses[MAX_CLASSES];
/* If the struct is larger than 32 bytes, pass it on the stack. */
if (type->size > 32)
return 0;
for (i = 0; i < words; i++)
classes[i] = X86_64_NO_CLASS;
/* Zero sized arrays or structures are NO_CLASS. We return 0 to
signalize memory class, so handle it as special case. */
if (!words)
{
classes[0] = X86_64_NO_CLASS;
return 1;
}
/* Merge the fields of structure. */
for (ptr = type->elements; *ptr != NULL; ptr++)
{
int num;
byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
num = classify_argument (*ptr, subclasses, byte_offset % 8);
if (num == 0)
return 0;
for (i = 0; i < num; i++)
{
int pos = byte_offset / 8;
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
}
byte_offset += (*ptr)->size;
}
if (words > 2)
{
/* When size > 16 bytes, if the first one isn't
X86_64_SSE_CLASS or any other ones aren't
X86_64_SSEUP_CLASS, everything should be passed in
memory. */
if (classes[0] != X86_64_SSE_CLASS)
return 0;
for (i = 1; i < words; i++)
if (classes[i] != X86_64_SSEUP_CLASS)
return 0;
}
/* Final merger cleanup. */
for (i = 0; i < words; i++)
{
/* If one class is MEMORY, everything should be passed in
memory. */
if (classes[i] == X86_64_MEMORY_CLASS)
return 0;
/* The X86_64_SSEUP_CLASS should be always preceded by
X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
if (classes[i] == X86_64_SSEUP_CLASS
&& classes[i - 1] != X86_64_SSE_CLASS
&& classes[i - 1] != X86_64_SSEUP_CLASS)
{
/* The first one should never be X86_64_SSEUP_CLASS. */
FFI_ASSERT (i != 0);
classes[i] = X86_64_SSE_CLASS;
}
/* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
everything should be passed in memory. */
if (classes[i] == X86_64_X87UP_CLASS
&& (classes[i - 1] != X86_64_X87_CLASS))
{
/* The first one should never be X86_64_X87UP_CLASS. */
FFI_ASSERT (i != 0);
return 0;
}
}
return words;
}
default:
FFI_ASSERT(0);
}
return 0; /* Never reached. */
}
/* Examine the argument and return set number of register required in each
class. Return zero iff parameter should be passed in memory, otherwise
the number of registers. */
static int
examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
_Bool in_return, int *pngpr, int *pnsse)
{
int i, n, ngpr, nsse;
n = classify_argument (type, classes, 0);
if (n == 0)
return 0;
ngpr = nsse = 0;
for (i = 0; i < n; ++i)
switch (classes[i])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
ngpr++;
break;
case X86_64_SSE_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
nsse++;
break;
case X86_64_NO_CLASS:
case X86_64_SSEUP_CLASS:
break;
case X86_64_X87_CLASS:
case X86_64_X87UP_CLASS:
case X86_64_COMPLEX_X87_CLASS:
return in_return != 0;
default:
abort ();
}
*pngpr = ngpr;
*pnsse = nsse;
return n;
}
/* Perform machine dependent cif processing. */
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
enum x86_64_reg_class classes[MAX_CLASSES];
size_t bytes;
gprcount = ssecount = 0;
flags = cif->rtype->type;
if (flags != FFI_TYPE_VOID)
{
n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
if (n == 0)
{
/* The return value is passed in memory. A pointer to that
memory is the first argument. Allocate a register for it. */
gprcount++;
/* We don't have to do anything in asm for the return. */
flags = FFI_TYPE_VOID;
}
else if (flags == FFI_TYPE_STRUCT)
{
/* Mark which registers the result appears in. */
_Bool sse0 = SSE_CLASS_P (classes[0]);
_Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
if (sse0 && !sse1)
flags |= 1 << 8;
else if (!sse0 && sse1)
flags |= 1 << 9;
else if (sse0 && sse1)
flags |= 1 << 10;
/* Mark the true size of the structure. */
flags |= cif->rtype->size << 12;
}
}
/* Go over all arguments and determine the way they should be passed.
If it's in a register and there is space for it, let that be so. If
not, add it's size to the stack byte count. */
for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
{
if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
|| gprcount + ngpr > MAX_GPR_REGS
|| ssecount + nsse > MAX_SSE_REGS)
{
long align = cif->arg_types[i]->alignment;
if (align < 8)
align = 8;
bytes = ALIGN (bytes, align);
bytes += cif->arg_types[i]->size;
}
else
{
gprcount += ngpr;
ssecount += nsse;
}
}
if (ssecount)
flags |= 1 << 11;
cif->flags = flags;
cif->bytes = ALIGN (bytes, 8);
return FFI_OK;
}
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
enum x86_64_reg_class classes[MAX_CLASSES];
char *stack, *argp;
ffi_type **arg_types;
int gprcount, ssecount, ngpr, nsse, i, avn;
_Bool ret_in_memory;
struct register_args *reg_args;
/* Can't call 32-bit mode from 64-bit mode. */
FFI_ASSERT (cif->abi == FFI_UNIX64);
/* If the return value is a struct and we don't have a return value
address then we need to make one. Note the setting of flags to
VOID above in ffi_prep_cif_machdep. */
ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
&& (cif->flags & 0xff) == FFI_TYPE_VOID);
if (rvalue == NULL && ret_in_memory)
rvalue = alloca (cif->rtype->size);
/* Allocate the space for the arguments, plus 4 words of temp space. */
stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
reg_args = (struct register_args *) stack;
argp = stack + sizeof (struct register_args);
gprcount = ssecount = 0;
/* If the return value is passed in memory, add the pointer as the
first integer argument. */
if (ret_in_memory)
reg_args->gpr[gprcount++] = (long) rvalue;
avn = cif->nargs;
arg_types = cif->arg_types;
for (i = 0; i < avn; ++i)
{
size_t size = arg_types[i]->size;
int n;
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
if (n == 0
|| gprcount + ngpr > MAX_GPR_REGS
|| ssecount + nsse > MAX_SSE_REGS)
{
long align = arg_types[i]->alignment;
/* Stack arguments are *always* at least 8 byte aligned. */
if (align < 8)
align = 8;
/* Pass this argument in memory. */
argp = (void *) ALIGN (argp, align);
memcpy (argp, avalue[i], size);
argp += size;
}
else
{
/* The argument is passed entirely in registers. */
char *a = (char *) avalue[i];
int j;
for (j = 0; j < n; j++, a += 8, size -= 8)
{
switch (classes[j])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
reg_args->gpr[gprcount] = 0;
memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
gprcount++;
break;
case X86_64_SSE_CLASS:
case X86_64_SSEDF_CLASS:
reg_args->sse[ssecount++] = *(UINT64 *) a;
break;
case X86_64_SSESF_CLASS:
reg_args->sse[ssecount++] = *(UINT32 *) a;
break;
default:
abort();
}
}
}
}
ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
cif->flags, rvalue, fn, ssecount);
}
extern void ffi_closure_unix64(void);
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data,
void *codeloc)
{
volatile unsigned short *tramp;
/* Sanity check on the cif ABI. */
{
int abi = cif->abi;
if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
return FFI_BAD_ABI;
}
tramp = (volatile unsigned short *) &closure->tramp[0];
tramp[0] = 0xbb49; /* mov <code>, %r11 */
*(void * volatile *) &tramp[1] = ffi_closure_unix64;
tramp[5] = 0xba49; /* mov <data>, %r10 */
*(void * volatile *) &tramp[6] = codeloc;
/* Set the carry bit iff the function uses any sse registers.
This is clc or stc, together with the first byte of the jmp. */
tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
tramp[11] = 0xe3ff; /* jmp *%r11 */
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}
int
ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
struct register_args *reg_args, char *argp)
{
ffi_cif *cif;
void **avalue;
ffi_type **arg_types;
long i, avn;
int gprcount, ssecount, ngpr, nsse;
int ret;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
gprcount = ssecount = 0;
ret = cif->rtype->type;
if (ret != FFI_TYPE_VOID)
{
enum x86_64_reg_class classes[MAX_CLASSES];
int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
if (n == 0)
{
/* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */
rvalue = (void *) reg_args->gpr[gprcount++];
/* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID;
}
else if (ret == FFI_TYPE_STRUCT && n == 2)
{
/* Mark which register the second word of the structure goes in. */
_Bool sse0 = SSE_CLASS_P (classes[0]);
_Bool sse1 = SSE_CLASS_P (classes[1]);
if (!sse0 && sse1)
ret |= 1 << 8;
else if (sse0 && !sse1)
ret |= 1 << 9;
}
}
avn = cif->nargs;
arg_types = cif->arg_types;
for (i = 0; i < avn; ++i)
{
enum x86_64_reg_class classes[MAX_CLASSES];
int n;
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
if (n == 0
|| gprcount + ngpr > MAX_GPR_REGS
|| ssecount + nsse > MAX_SSE_REGS)
{
long align = arg_types[i]->alignment;
/* Stack arguments are *always* at least 8 byte aligned. */
if (align < 8)
align = 8;
/* Pass this argument in memory. */
argp = (void *) ALIGN (argp, align);
avalue[i] = argp;
argp += arg_types[i]->size;
}
/* If the argument is in a single register, or two consecutive
integer registers, then we can use that address directly. */
else if (n == 1
|| (n == 2 && !(SSE_CLASS_P (classes[0])
|| SSE_CLASS_P (classes[1]))))
{
/* The argument is in a single register. */
if (SSE_CLASS_P (classes[0]))
{
avalue[i] = &reg_args->sse[ssecount];
ssecount += n;
}
else
{
avalue[i] = &reg_args->gpr[gprcount];
gprcount += n;
}
}
/* Otherwise, allocate space to make them consecutive. */
else
{
char *a = alloca (16);
int j;
avalue[i] = a;
for (j = 0; j < n; j++, a += 8)
{
if (SSE_CLASS_P (classes[j]))
memcpy (a, &reg_args->sse[ssecount++], 8);
else
memcpy (a, &reg_args->gpr[gprcount++], 8);
}
}
}
/* Invoke the closure. */
closure->fun (cif, rvalue, avalue, closure->user_data);
/* Tell assembly how to perform return type promotions. */
return ret;
}
#endif /* __x86_64__ */

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -1364,7 +1364,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1435,7 +1435,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1544,7 +1544,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2145,7 +2145,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3078,7 +3078,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -14049,7 +14049,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14119,7 +14119,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -145,6 +145,7 @@ See the ChangeLog files for details.
3.0.10 ???-??-??
Add support for Apple's iOS.
Add support for ARM VFP ABI.
Add RTEMS support for MIPS and M68K.
Fix the N64 build on mips-sgi-irix6.5.
Enable builds with Microsoft's compiler.

44
.pc/interix/configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -621,9 +621,6 @@ FFI_DEBUG_FALSE
FFI_DEBUG_TRUE
TARGETDIR
TARGET
FFI_EXEC_TRAMPOLINE_TABLE
FFI_EXEC_TRAMPOLINE_TABLE_FALSE
FFI_EXEC_TRAMPOLINE_TABLE_TRUE
sys_symbol_underscore
HAVE_LONG_DOUBLE
ALLOCA
@@ -1370,7 +1367,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1441,7 +1438,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1550,7 +1547,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2151,7 +2148,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3084,7 +3081,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -13285,30 +13282,13 @@ $as_echo "#define SYMBOL_UNDERSCORE 1" >>confdefs.h
fi
fi
FFI_EXEC_TRAMPOLINE_TABLE=0
case "$target" in
*arm*-apple-darwin*)
FFI_EXEC_TRAMPOLINE_TABLE=1
$as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h
;;
*-apple-darwin10* | *-*-freebsd* | *-*-openbsd* | *-pc-solaris*)
$as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h
;;
esac
if test x$FFI_EXEC_TRAMPOLINE_TABLE = x1; then
FFI_EXEC_TRAMPOLINE_TABLE_TRUE=
FFI_EXEC_TRAMPOLINE_TABLE_FALSE='#'
else
FFI_EXEC_TRAMPOLINE_TABLE_TRUE='#'
FFI_EXEC_TRAMPOLINE_TABLE_FALSE=
fi
if test x$TARGET = xX86_64; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
@@ -13730,10 +13710,6 @@ if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then
as_fn_error $? "conditional \"FFI_DEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -14147,7 +14123,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14217,7 +14193,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -1,5 +1,6 @@
2011-02-11 Anthony Green <green@moxielogic.com>
* libtool-version: Update.
* Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if
FFI_DEBUG.
(libffi_la_SOURCES): Remove src/debug.c

View File

@@ -142,6 +142,7 @@ See the ChangeLog files for details.
3.0.10 ???-??-??
Add support for Apple's iOS.
Add support for ARM VFP ABI.
Add RTEMS support for MIPS and M68K.
Fix the N64 build on mips-sgi-irix6.5.
Enable builds with Microsoft's compiler.

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -138,6 +138,7 @@ See the ChangeLog files for details.
3.0.10 ???-??-??
Add support for Apple's iOS.
Add support for ARM VFP ABI.
Add RTEMS support for MIPS and M68K.
Fix the N64 build on mips-sgi-irix6.5.
Enable builds with Microsoft's compiler.

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -621,9 +621,6 @@ FFI_DEBUG_FALSE
FFI_DEBUG_TRUE
TARGETDIR
TARGET
FFI_EXEC_TRAMPOLINE_TABLE
FFI_EXEC_TRAMPOLINE_TABLE_FALSE
FFI_EXEC_TRAMPOLINE_TABLE_TRUE
sys_symbol_underscore
HAVE_LONG_DOUBLE
ALLOCA
@@ -1370,7 +1367,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1441,7 +1438,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1550,7 +1547,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2151,7 +2148,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3084,7 +3081,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -13285,30 +13282,13 @@ $as_echo "#define SYMBOL_UNDERSCORE 1" >>confdefs.h
fi
fi
FFI_EXEC_TRAMPOLINE_TABLE=0
case "$target" in
*arm*-apple-darwin*)
FFI_EXEC_TRAMPOLINE_TABLE=1
$as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h
;;
*-apple-darwin10* | *-*-freebsd* | *-*-openbsd* | *-pc-solaris*)
$as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h
;;
esac
if test x$FFI_EXEC_TRAMPOLINE_TABLE = x1; then
FFI_EXEC_TRAMPOLINE_TABLE_TRUE=
FFI_EXEC_TRAMPOLINE_TABLE_FALSE='#'
else
FFI_EXEC_TRAMPOLINE_TABLE_TRUE='#'
FFI_EXEC_TRAMPOLINE_TABLE_FALSE=
fi
if test x$TARGET = xX86_64; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
@@ -13730,10 +13710,6 @@ if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then
as_fn_error $? "conditional \"FFI_DEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -14147,7 +14123,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14217,7 +14193,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -0,0 +1,29 @@
# This file is used to maintain libtool version info for libffi. See
# the libtool manual to understand the meaning of the fields. This is
# a separate file so that version updates don't involve re-running
# automake.
#
# Here are a set of rules to help you update your library version
# information:
#
# 1. Start with version information of `0:0:0' for each libtool library.
#
# 2. Update the version information only immediately before a public
# release of your software. More frequent updates are unnecessary,
# and only guarantee that the current interface number gets larger
# faster.
#
# 3. If the library source code has changed at all since the last
# update, then increment revision (`c:r:a' becomes `c:r+1:a').
#
# 4. If any interfaces have been added, removed, or changed since the
# last update, increment current, and set revision to 0.
#
# 5. If any interfaces have been added since the last public release,
# then increment age.
#
# 6. If any interfaces have been removed since the last public
# release, then set age to 0.
#
# CURRENT:REVISION:AGE
5:10:0

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -621,9 +621,6 @@ FFI_DEBUG_FALSE
FFI_DEBUG_TRUE
TARGETDIR
TARGET
FFI_EXEC_TRAMPOLINE_TABLE
FFI_EXEC_TRAMPOLINE_TABLE_FALSE
FFI_EXEC_TRAMPOLINE_TABLE_TRUE
sys_symbol_underscore
HAVE_LONG_DOUBLE
ALLOCA
@@ -1370,7 +1367,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1441,7 +1438,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1550,7 +1547,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2151,7 +2148,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3084,7 +3081,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -13285,30 +13282,13 @@ $as_echo "#define SYMBOL_UNDERSCORE 1" >>confdefs.h
fi
fi
FFI_EXEC_TRAMPOLINE_TABLE=0
case "$target" in
*arm*-apple-darwin*)
FFI_EXEC_TRAMPOLINE_TABLE=1
$as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h
;;
*-apple-darwin10* | *-*-freebsd* | *-*-openbsd* | *-pc-solaris*)
$as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h
;;
esac
if test x$FFI_EXEC_TRAMPOLINE_TABLE = x1; then
FFI_EXEC_TRAMPOLINE_TABLE_TRUE=
FFI_EXEC_TRAMPOLINE_TABLE_FALSE='#'
else
FFI_EXEC_TRAMPOLINE_TABLE_TRUE='#'
FFI_EXEC_TRAMPOLINE_TABLE_FALSE=
fi
if test x$TARGET = xX86_64; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
@@ -13730,10 +13710,6 @@ if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then
as_fn_error $? "conditional \"FFI_DEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -14147,7 +14123,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14217,7 +14193,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -1366,7 +1366,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1437,7 +1437,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1546,7 +1546,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2147,7 +2147,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3080,7 +3080,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -14067,7 +14067,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14137,7 +14137,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -1367,7 +1367,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1438,7 +1438,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1547,7 +1547,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2148,7 +2148,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3081,7 +3081,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -14123,7 +14123,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14193,7 +14193,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -1,5 +1,23 @@
2011-02-13 Anthony Green <green@moxielogic.com>
* include/ffi_common.h (UNLIKELY, LIKELY): Define.
* src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition.
* src/prep_cif.c (UNLIKELY, LIKELY): Remove definition.
* src/prep_cif.c (initialize_aggregate): Convert assertion into
FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0.
* src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
just return FFI_BAD_ABI when things are wrong.
* src/arm/ffi.c (ffi_prep_closure_loc): Ditto.
* src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto.
* src/mips/ffi.c (ffi_prep_closure_loc): Ditto.
* src/ia64/ffi.c (ffi_prep_closure_loc): Ditto.
* src/avr32/ffi.c (ffi_prep_closure_loc): Ditto.
2011-02-11 Anthony Green <green@moxielogic.com>
* libtool-version: Update.
* Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if
FFI_DEBUG.
(libffi_la_SOURCES): Remove src/debug.c

1
README
View File

@@ -146,6 +146,7 @@ See the ChangeLog files for details.
3.0.10 ???-??-??
Add support for Apple's iOS.
Add support for ARM VFP ABI.
Add RTEMS support for MIPS and M68K.
Fix the N64 build on mips-sgi-irix6.5.
Enable builds with Microsoft's compiler.

8
aclocal.m4 vendored
View File

@@ -1857,6 +1857,14 @@ AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([m4/ax_cc_maxopt.m4])
m4_include([m4/ax_cflags_warn_all.m4])
m4_include([m4/ax_check_compiler_flags.m4])
m4_include([m4/ax_compiler_vendor.m4])
m4_include([m4/ax_configure_args.m4])
m4_include([m4/ax_enable_builddir.m4])
m4_include([m4/ax_gcc_archflag.m4])
m4_include([m4/ax_gcc_x86_cpuid.m4])
m4_include([m4/libtool.m4])
m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4])

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
#
# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libffi'
PACKAGE_TARNAME='libffi'
PACKAGE_VERSION='3.0.10rc4'
PACKAGE_STRING='libffi 3.0.10rc4'
PACKAGE_VERSION='3.0.10rc5'
PACKAGE_STRING='libffi 3.0.10rc5'
PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -1375,7 +1375,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1446,7 +1446,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -1562,7 +1562,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libffi configure 3.0.10rc4
libffi configure 3.0.10rc5
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2163,7 +2163,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libffi $as_me 3.0.10rc4, which was
It was created by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3197,7 +3197,7 @@ fi
# Define the identity of the package.
PACKAGE='libffi'
VERSION='3.0.10rc4'
VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -15185,7 +15185,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libffi $as_me 3.0.10rc4, which was
This file was extended by libffi $as_me 3.0.10rc5, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15255,7 +15255,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libffi config.status 3.0.10rc4
libffi config.status 3.0.10rc5
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
AC_PREREQ(2.63)
AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
AC_CANONICAL_SYSTEM

View File

@@ -39,10 +39,18 @@ subdir = include
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/ffi.h.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compiler_flags.m4 \
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
$(top_srcdir)/m4/ax_configure_args.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -141,6 +149,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -161,6 +170,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_enable_builddir_sed = @ax_enable_builddir_sed@
bindir = @bindir@
build = @build@
build_alias = @build_alias@

View File

@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Copyright (C) 2007 Free Software Foundation, Inc
ffi_common.h - Copyright (C) 2011 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc
Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
@@ -112,11 +113,14 @@ typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),1)
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -26,4 +26,4 @@
# release, then set age to 0.
#
# CURRENT:REVISION:AGE
5:10:0
6:0:0

View File

@@ -37,10 +37,18 @@ target_triplet = @target@
subdir = man
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compiler_flags.m4 \
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
$(top_srcdir)/m4/ax_configure_args.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -139,6 +147,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -159,6 +168,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_enable_builddir_sed = @ax_enable_builddir_sed@
bindir = @bindir@
build = @build@
build_alias = @build_alias@

286
patches/bad-abi-fix Normal file
View File

@@ -0,0 +1,286 @@
Index: libffi/ChangeLog
===================================================================
--- libffi.orig/ChangeLog
+++ libffi/ChangeLog
@@ -1,3 +1,20 @@
+2011-02-13 Anthony Green <green@moxielogic.com>
+
+ * include/ffi_common.h (UNLIKELY, LIKELY): Define.
+ * src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition.
+ * src/prep_cif.c (UNLIKELY, LIKELY): Remove definition.
+
+ * src/prep_cif.c (initialize_aggregate): Convert assertion into
+ FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0.
+
+ * src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
+ just return FFI_BAD_ABI when things are wrong.
+ * src/arm/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/mips/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/ia64/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/avr32/ffi.c (ffi_prep_closure_loc): Ditto.
+
2011-02-11 Anthony Green <green@moxielogic.com>
* libtool-version: Update.
Index: libffi/include/ffi_common.h
===================================================================
--- libffi.orig/include/ffi_common.h
+++ libffi/include/ffi_common.h
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
- Copyright (C) 2007 Free Software Foundation, Inc
-
+ ffi_common.h - Copyright (C) 2011 Anthony Green
+ Copyright (C) 2007 Free Software Foundation, Inc
+ Copyright (c) 1996 Red Hat, Inc.
+
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
@@ -112,11 +113,14 @@ typedef signed int SINT64 __attribute_
typedef float FLOAT32;
+#ifndef __GNUC__
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#define LIKELY(x) __builtin_expect((x),1)
+#define UNLIKELY(x) __builtin_expect((x),1)
#ifdef __cplusplus
}
#endif
#endif
-
-
Index: libffi/src/arm/ffi.c
===================================================================
--- libffi.orig/src/arm/ffi.c
+++ libffi/src/arm/ffi.c
@@ -1,7 +1,9 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
- Copyright (c) 2011 Plausible Labs Cooperative, Inc.
-
+ ffi.c - Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+ Copyright (c) 2011 Anthony Green
+ Copyright (c) 2011 Free Software Foundation
+ Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
+
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@@ -582,7 +584,7 @@ ffi_prep_closure_loc (ffi_closure* closu
else if (cif->abi == FFI_VFP)
closure_func = &ffi_closure_VFP;
else
- FFI_ASSERT (0);
+ return FFI_BAD_ABI;
#if FFI_EXEC_TRAMPOLINE_TABLE
void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
Index: libffi/src/avr32/ffi.c
===================================================================
--- libffi.orig/src/avr32/ffi.c
+++ libffi/src/avr32/ffi.c
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
+ ffi.c - Copyright (c) 2011 Anthony Green
+ Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
AVR32 Foreign Function Interface
@@ -394,7 +395,8 @@ ffi_status ffi_prep_closure_loc(ffi_clos
void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
void *codeloc)
{
- FFI_ASSERT(cif->abi == FFI_SYSV);
+ if (cif->abi != FFI_SYSV)
+ return FFI_BAD_ABI;
unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);
Index: libffi/src/ia64/ffi.c
===================================================================
--- libffi.orig/src/ia64/ffi.c
+++ libffi/src/ia64/ffi.c
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
- Copyright (c) 2000 Hewlett Packard Company
-
+ ffi.c - Copyright (c) 2011 Anthony Green
+ Copyright (c) 2000 Hewlett Packard Company
+ Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
+
IA64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@@ -425,7 +426,8 @@ ffi_prep_closure_loc (ffi_closure* closu
struct ffi_ia64_trampoline_struct *tramp;
struct ia64_fd *fd;
- FFI_ASSERT (cif->abi == FFI_UNIX);
+ if (cif->abi != FFI_UNIX)
+ return FFI_BAD_ABI;
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
fd = (struct ia64_fd *)(void *)ffi_closure_unix;
Index: libffi/src/mips/ffi.c
===================================================================
--- libffi.orig/src/mips/ffi.c
+++ libffi/src/mips/ffi.c
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc.
- Copyright (c) 2008 David Daney
+ ffi.c - Copyright (c) 2011 Anthony Green
+ Copyright (c) 2008 David Daney
+ Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
MIPS Foreign Function Interface
@@ -662,10 +663,12 @@ ffi_prep_closure_loc (ffi_closure *closu
char *clear_location = (char *) codeloc;
#if defined(FFI_MIPS_O32)
- FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
+ if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
+ return FFI_BAD_ABI;
fn = ffi_closure_O32;
#else /* FFI_MIPS_N32 */
- FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
+ if (cif->abi != FFI_N32 && cif->abi != FFI_N64)
+ return FFI_BAD_ABI;
fn = ffi_closure_N32;
#endif /* FFI_MIPS_O32 */
Index: libffi/src/pa/ffi.c
===================================================================
--- libffi.orig/src/pa/ffi.c
+++ libffi/src/pa/ffi.c
@@ -1,9 +1,11 @@
/* -----------------------------------------------------------------------
- ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
+ ffi.c - (c) 2011 Anthony Green
(c) 2008 Red Hat, Inc.
-
+ (c) 2006 Free Software Foundation, Inc.
+ (c) 2003-2004 Randolph Chung <tausq@debian.org>
+
HPPA Foreign Function Interface
- HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
+ HP-UX PA ABI support
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -633,7 +635,8 @@ ffi_prep_closure_loc (ffi_closure* closu
UINT32 *tmp;
#endif
- FFI_ASSERT (cif->abi == FFI_PA32);
+ if (cif->abi != FFI_PA32)
+ return FFI_BAD_ABI;
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */
Index: libffi/src/powerpc/ffi.c
===================================================================
--- libffi.orig/src/powerpc/ffi.c
+++ libffi/src/powerpc/ffi.c
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998 Geoffrey Keating
- Copyright (C) 2007, 2008 Free Software Foundation, Inc
- Copyright (C) 2008 Red Hat, Inc
+ ffi.c - Copyright (C) 2011 Anthony Green
+ Copyright (C) 2008 Red Hat, Inc
+ Copyright (C) 2007, 2008 Free Software Foundation, Inc
+ Copyright (c) 1998 Geoffrey Keating
PowerPC Foreign Function Interface
@@ -949,14 +950,16 @@ ffi_prep_closure_loc (ffi_closure *closu
#ifdef POWERPC64
void **tramp = (void **) &closure->tramp[0];
- FFI_ASSERT (cif->abi == FFI_LINUX64);
+ if (cif->abi != FFI_LINUX64)
+ return FFI_BAD_ABI;
/* Copy function address and TOC from ffi_closure_LINUX64. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
tramp[2] = codeloc;
#else
unsigned int *tramp;
- FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
+ if (! (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV))
+ return FFI_BAD_ABI;
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */
Index: libffi/src/prep_cif.c
===================================================================
--- libffi.orig/src/prep_cif.c
+++ libffi/src/prep_cif.c
@@ -27,12 +27,6 @@
#include <ffi_common.h>
#include <stdlib.h>
-#ifndef __GNUC__
-#define __builtin_expect(x, expected_value) (x)
-#endif
-#define LIKELY(x) __builtin_expect((x),1)
-#define UNLIKELY(x) __builtin_expect((x),1)
-
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
@@ -44,11 +38,11 @@ static ffi_status initialize_aggregate(f
{
ffi_type **ptr;
- FFI_ASSERT(arg != NULL);
+ if (UNLIKELY(arg == NULL || arg->elements == NULL))
+ return FFI_BAD_TYPEDEF;
- FFI_ASSERT(arg->elements != NULL);
- FFI_ASSERT(arg->size == 0);
- FFI_ASSERT(arg->alignment == 0);
+ arg->size = 0;
+ arg->alignment = 0;
ptr = &(arg->elements[0]);
Index: libffi/src/x86/ffi64.c
===================================================================
--- libffi.orig/src/x86/ffi64.c
+++ libffi/src/x86/ffi64.c
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
+ ffi64.c - Copyright (c) 20011 Anthony Green
Copyright (c) 2008, 2010 Red Hat, Inc.
-
+ Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
+
x86-64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@@ -28,12 +29,6 @@
#include <ffi.h>
#include <ffi_common.h>
-#ifndef __GNUC__
-#define __builtin_expect(x, expected_value) (x)
-#endif
-#define LIKELY(x) __builtin_expect((x),1)
-#define UNLIKELY(x) __builtin_expect((x),1)
-
#include <stdlib.h>
#include <stdarg.h>

View File

@@ -2,7 +2,7 @@ Index: libffi/ChangeLog
===================================================================
--- libffi.orig/ChangeLog
+++ libffi/ChangeLog
@@ -43,7 +43,7 @@
@@ -44,7 +44,7 @@
* src/prep_cif.c (UNLIKELY, LIKELY): Define.
(initialize_aggregate): Check for bad types.

View File

@@ -2,9 +2,10 @@ Index: libffi/ChangeLog
===================================================================
--- libffi.orig/ChangeLog
+++ libffi/ChangeLog
@@ -1,5 +1,13 @@
@@ -1,5 +1,14 @@
2011-02-11 Anthony Green <green@moxielogic.com>
+ * libtool-version: Update.
+ * Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if
+ FFI_DEBUG.
+ (libffi_la_SOURCES): Remove src/debug.c
@@ -278,3 +279,13 @@ Index: libffi/Makefile.in
src/mips/$(am__dirstamp):
@$(MKDIR_P) src/mips
@: > src/mips/$(am__dirstamp)
Index: libffi/libtool-version
===================================================================
--- libffi.orig/libtool-version
+++ libffi/libtool-version
@@ -26,4 +26,4 @@
# release, then set age to 0.
#
# CURRENT:REVISION:AGE
-5:10:0
+6:0:0

View File

@@ -21,3 +21,4 @@ sparc-abi-check
remove-debug-code
ungccify
ios-fixes
bad-abi-fix

View File

@@ -4059,7 +4059,7 @@ Index: libffi/configure
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.64 for libffi 3.0.9.
+# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc4.
+# Generated by GNU Autoconf 2.68 for libffi 3.0.10rc5.
+#
+# Report bugs to <http://sourceware.org/libffi.html>.
#
@@ -4169,8 +4169,8 @@ Index: libffi/configure
-PACKAGE_VERSION='3.0.9'
-PACKAGE_STRING='libffi 3.0.9'
-PACKAGE_BUGREPORT='http://gcc.gnu.org/bugs.html'
+PACKAGE_VERSION='3.0.10rc4'
+PACKAGE_STRING='libffi 3.0.10rc4'
+PACKAGE_VERSION='3.0.10rc5'
+PACKAGE_STRING='libffi 3.0.10rc5'
+PACKAGE_BUGREPORT='http://sourceware.org/libffi.html'
PACKAGE_URL=''
@@ -4363,7 +4363,7 @@ Index: libffi/configure
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures libffi 3.0.9 to adapt to many kinds of systems.
+\`configure' configures libffi 3.0.10rc4 to adapt to many kinds of systems.
+\`configure' configures libffi 3.0.10rc5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -4381,7 +4381,7 @@ Index: libffi/configure
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of libffi 3.0.9:";;
+ short | recursive ) echo "Configuration of libffi 3.0.10rc4:";;
+ short | recursive ) echo "Configuration of libffi 3.0.10rc5:";;
esac
cat <<\_ACEOF
@@ -4426,7 +4426,7 @@ Index: libffi/configure
cat <<\_ACEOF
-libffi configure 3.0.9
-generated by GNU Autoconf 2.64
+libffi configure 3.0.10rc4
+libffi configure 3.0.10rc5
+generated by GNU Autoconf 2.68
-Copyright (C) 2009 Free Software Foundation, Inc.
@@ -4649,7 +4649,7 @@ Index: libffi/configure
-It was created by libffi $as_me 3.0.9, which was
-generated by GNU Autoconf 2.64. Invocation command line was
+It was created by libffi $as_me 3.0.10rc4, which was
+It was created by libffi $as_me 3.0.10rc5, which was
+generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -5048,7 +5048,7 @@ Index: libffi/configure
# Define the identity of the package.
PACKAGE='libffi'
- VERSION='3.0.9'
+ VERSION='3.0.10rc4'
+ VERSION='3.0.10rc5'
cat >>confdefs.h <<_ACEOF
@@ -7920,7 +7920,7 @@ Index: libffi/configure
ac_log="
-This file was extended by libffi $as_me 3.0.9, which was
-generated by GNU Autoconf 2.64. Invocation command line was
+This file was extended by libffi $as_me 3.0.10rc4, which was
+This file was extended by libffi $as_me 3.0.10rc5, which was
+generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -7947,7 +7947,7 @@ Index: libffi/configure
-libffi config.status 3.0.9
-configured by $0, generated by GNU Autoconf 2.64,
- with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+libffi config.status 3.0.10rc4
+libffi config.status 3.0.10rc5
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
@@ -8977,7 +8977,7 @@ Index: libffi/configure.ac
+AC_PREREQ(2.63)
-AC_INIT([libffi], [3.0.9], [http://gcc.gnu.org/bugs.html])
+AC_INIT([libffi], [3.0.10rc4], [http://sourceware.org/libffi.html])
+AC_INIT([libffi], [3.0.10rc5], [http://sourceware.org/libffi.html])
AC_CONFIG_HEADERS([fficonfig.h])
-AM_ENABLE_MULTILIB(, ..)
@@ -28001,11 +28001,12 @@ Index: libffi/README
|--------------+------------------|
Please send additional platform test results to
@@ -136,10 +137,14 @@ History
@@ -136,10 +137,15 @@ History
See the ChangeLog files for details.
3.0.10 ???-??-??
+ Add support for Apple's iOS.
+ Add support for ARM VFP ABI.
+ Add RTEMS support for MIPS and M68K.
Fix the N64 build on mips-sgi-irix6.5.
- Testsuite fixes for Tru64 Unix.
@@ -28018,7 +28019,7 @@ Index: libffi/README
3.0.9 Dec-31-09
Add AVR32 and win64 ports. Add ARM softfp support.
@@ -320,5 +325,6 @@ Alex Oliva solved the executable page pr
@@ -320,5 +326,6 @@ Alex Oliva solved the executable page pr
The list above is almost certainly incomplete and inaccurate. I'm
happy to make corrections or additions upon request.

View File

@@ -83,7 +83,17 @@ Index: libffi/configure
===================================================================
--- libffi.orig/configure
+++ libffi/configure
@@ -688,6 +688,7 @@ TESTSUBDIR_TRUE
@@ -621,6 +621,9 @@ FFI_DEBUG_FALSE
FFI_DEBUG_TRUE
TARGETDIR
TARGET
+FFI_EXEC_TRAMPOLINE_TABLE
+FFI_EXEC_TRAMPOLINE_TABLE_FALSE
+FFI_EXEC_TRAMPOLINE_TABLE_TRUE
sys_symbol_underscore
HAVE_LONG_DOUBLE
ALLOCA
@@ -685,6 +688,7 @@ TESTSUBDIR_TRUE
MAINT
MAINTAINER_MODE_FALSE
MAINTAINER_MODE_TRUE
@@ -91,7 +101,7 @@ Index: libffi/configure
CPP
OTOOL64
OTOOL
@@ -754,6 +755,7 @@ am__isrc
@@ -751,6 +755,7 @@ am__isrc
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
@@ -99,7 +109,7 @@ Index: libffi/configure
target_os
target_vendor
target_cpu
@@ -807,6 +809,7 @@ SHELL'
@@ -804,6 +809,7 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
@@ -107,7 +117,7 @@ Index: libffi/configure
enable_dependency_tracking
enable_shared
enable_static
@@ -815,6 +818,8 @@ enable_fast_install
@@ -812,6 +818,8 @@ enable_fast_install
with_gnu_ld
with_sysroot
enable_libtool_lock
@@ -116,7 +126,7 @@ Index: libffi/configure
enable_maintainer_mode
enable_debug
enable_structs
@@ -1449,6 +1454,8 @@ Optional Features:
@@ -1446,6 +1454,8 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
@@ -125,7 +135,7 @@ Index: libffi/configure
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
--enable-shared[=PKGS] build shared libraries [default=yes]
@@ -1456,6 +1463,9 @@ Optional Features:
@@ -1453,6 +1463,9 @@ Optional Features:
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
@@ -135,7 +145,7 @@ Index: libffi/configure
--enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer
--enable-debug debugging mode
@@ -1471,6 +1481,8 @@ Optional Packages:
@@ -1468,6 +1481,8 @@ Optional Packages:
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-sysroot=DIR Search for dependent libraries within DIR
(or the compiler's sysroot if not specified).
@@ -144,7 +154,7 @@ Index: libffi/configure
Some influential environment variables:
CC C compiler command
@@ -2646,6 +2658,110 @@ target_alias=${target_alias-$host_alias}
@@ -2643,6 +2658,110 @@ target_alias=${target_alias-$host_alias}
. ${srcdir}/configure.host
@@ -255,7 +265,7 @@ Index: libffi/configure
am__api_version='1.11'
# Find a good install program. We prefer a C program (faster),
@@ -2803,9 +2919,6 @@ test "$program_suffix" != NONE &&
@@ -2800,9 +2919,6 @@ test "$program_suffix" != NONE &&
ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
@@ -265,7 +275,7 @@ Index: libffi/configure
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
@@ -11837,201 +11950,1126 @@ CC="$lt_save_CC"
@@ -11834,201 +11950,1126 @@ CC="$lt_save_CC"
@@ -1548,7 +1558,49 @@ Index: libffi/configure
fi
@@ -14336,6 +15374,14 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_writ
@@ -13282,13 +14323,30 @@ $as_echo "#define SYMBOL_UNDERSCORE 1" >
fi
fi
+
+FFI_EXEC_TRAMPOLINE_TABLE=0
case "$target" in
+ *arm*-apple-darwin*)
+ FFI_EXEC_TRAMPOLINE_TABLE=1
+
+$as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h
+
+ ;;
*-apple-darwin10* | *-*-freebsd* | *-*-openbsd* | *-pc-solaris*)
$as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h
;;
esac
+ if test x$FFI_EXEC_TRAMPOLINE_TABLE = x1; then
+ FFI_EXEC_TRAMPOLINE_TABLE_TRUE=
+ FFI_EXEC_TRAMPOLINE_TABLE_FALSE='#'
+else
+ FFI_EXEC_TRAMPOLINE_TABLE_TRUE='#'
+ FFI_EXEC_TRAMPOLINE_TABLE_FALSE=
+fi
+
+
if test x$TARGET = xX86_64; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
@@ -13710,6 +14768,10 @@ if test -z "${PA64_HPUX_TRUE}" && test -
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
+ as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then
as_fn_error $? "conditional \"FFI_DEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -14312,6 +15374,14 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_writ
#
# INIT-COMMANDS
#
@@ -1563,7 +1615,7 @@ Index: libffi/configure
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
@@ -14625,6 +15671,7 @@ for ac_config_target in $ac_config_targe
@@ -14601,6 +15671,7 @@ for ac_config_target in $ac_config_targe
do
case $ac_config_target in
"fficonfig.h") CONFIG_HEADERS="$CONFIG_HEADERS fficonfig.h" ;;
@@ -1571,7 +1623,7 @@ Index: libffi/configure
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
"libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
"include") CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;;
@@ -15263,6 +16310,150 @@ $as_echo "$as_me: executing $ac_file com
@@ -15239,6 +16310,150 @@ $as_echo "$as_me: executing $ac_file com
case $ac_file$ac_mode in

View File

@@ -1,6 +1,8 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
ffi.c - Copyright (c) 2011 Plausible Labs Cooperative, Inc.
Copyright (c) 2011 Anthony Green
Copyright (c) 2011 Free Software Foundation
Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
ARM Foreign Function Interface
@@ -582,7 +584,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
else if (cif->abi == FFI_VFP)
closure_func = &ffi_closure_VFP;
else
FFI_ASSERT (0);
return FFI_BAD_ABI;
#if FFI_EXEC_TRAMPOLINE_TABLE
void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);

View File

@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
AVR32 Foreign Function Interface
@@ -394,7 +395,8 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
void *codeloc)
{
FFI_ASSERT(cif->abi == FFI_SYSV);
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);

View File

@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
Copyright (c) 2000 Hewlett Packard Company
ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 2000 Hewlett Packard Company
Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
IA64 Foreign Function Interface
@@ -425,7 +426,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
struct ffi_ia64_trampoline_struct *tramp;
struct ia64_fd *fd;
FFI_ASSERT (cif->abi == FFI_UNIX);
if (cif->abi != FFI_UNIX)
return FFI_BAD_ABI;
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
fd = (struct ia64_fd *)(void *)ffi_closure_unix;

View File

@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc.
Copyright (c) 2008 David Daney
ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 2008 David Daney
Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
MIPS Foreign Function Interface
@@ -662,10 +663,12 @@ ffi_prep_closure_loc (ffi_closure *closure,
char *clear_location = (char *) codeloc;
#if defined(FFI_MIPS_O32)
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
return FFI_BAD_ABI;
fn = ffi_closure_O32;
#else /* FFI_MIPS_N32 */
FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
if (cif->abi != FFI_N32 && cif->abi != FFI_N64)
return FFI_BAD_ABI;
fn = ffi_closure_N32;
#endif /* FFI_MIPS_O32 */

View File

@@ -1,9 +1,11 @@
/* -----------------------------------------------------------------------
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
ffi.c - (c) 2011 Anthony Green
(c) 2008 Red Hat, Inc.
(c) 2006 Free Software Foundation, Inc.
(c) 2003-2004 Randolph Chung <tausq@debian.org>
HPPA Foreign Function Interface
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
HP-UX PA ABI support
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -633,7 +635,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
UINT32 *tmp;
#endif
FFI_ASSERT (cif->abi == FFI_PA32);
if (cif->abi != FFI_PA32)
return FFI_BAD_ABI;
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */

View File

@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998 Geoffrey Keating
Copyright (C) 2007, 2008 Free Software Foundation, Inc
Copyright (C) 2008 Red Hat, Inc
ffi.c - Copyright (C) 2011 Anthony Green
Copyright (C) 2008 Red Hat, Inc
Copyright (C) 2007, 2008 Free Software Foundation, Inc
Copyright (c) 1998 Geoffrey Keating
PowerPC Foreign Function Interface
@@ -949,14 +950,16 @@ ffi_prep_closure_loc (ffi_closure *closure,
#ifdef POWERPC64
void **tramp = (void **) &closure->tramp[0];
FFI_ASSERT (cif->abi == FFI_LINUX64);
if (cif->abi != FFI_LINUX64)
return FFI_BAD_ABI;
/* Copy function address and TOC from ffi_closure_LINUX64. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
tramp[2] = codeloc;
#else
unsigned int *tramp;
FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
if (! (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV))
return FFI_BAD_ABI;
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */

View File

@@ -27,12 +27,6 @@
#include <ffi_common.h>
#include <stdlib.h>
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),1)
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
@@ -44,11 +38,11 @@ static ffi_status initialize_aggregate(ffi_type *arg)
{
ffi_type **ptr;
FFI_ASSERT(arg != NULL);
if (UNLIKELY(arg == NULL || arg->elements == NULL))
return FFI_BAD_TYPEDEF;
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
FFI_ASSERT(arg->alignment == 0);
arg->size = 0;
arg->alignment = 0;
ptr = &(arg->elements[0]);

View File

@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
ffi64.c - Copyright (c) 20011 Anthony Green
Copyright (c) 2008, 2010 Red Hat, Inc.
Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
x86-64 Foreign Function Interface
@@ -28,12 +29,6 @@
#include <ffi.h>
#include <ffi_common.h>
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),1)
#include <stdlib.h>
#include <stdarg.h>

View File

@@ -37,10 +37,18 @@ target_triplet = @target@
subdir = testsuite
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cc_maxopt.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compiler_flags.m4 \
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
$(top_srcdir)/m4/ax_configure_args.m4 \
$(top_srcdir)/m4/ax_enable_builddir.m4 \
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -116,6 +124,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PRTDIAG = @PRTDIAG@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -136,6 +145,7 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_enable_builddir_sed = @ax_enable_builddir_sed@
bindir = @bindir@
build = @build@
build_alias = @build_alias@