arm: Reindent arm/ffi.c

This commit is contained in:
Richard Henderson
2014-10-15 17:28:53 -04:00
parent 9761b7bb70
commit c129bea82a

View File

@@ -37,10 +37,11 @@
static int vfp_type_p (ffi_type *); static int vfp_type_p (ffi_type *);
static void layout_vfp_args (ffi_cif *); static void layout_vfp_args (ffi_cif *);
int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space); int ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space);
int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space); int ffi_prep_args_VFP (char *stack, extended_cif *ecif, float *vfp_space);
static char* ffi_align(ffi_type **p_arg, char *argp) static char *
ffi_align (ffi_type **p_arg, char *argp)
{ {
/* Align if necessary */ /* Align if necessary */
register size_t alignment = (*p_arg)->alignment; register size_t alignment = (*p_arg)->alignment;
@@ -56,68 +57,70 @@ static char* ffi_align(ffi_type **p_arg, char *argp)
#endif #endif
if ((alignment - 1) & (unsigned) argp) if ((alignment - 1) & (unsigned) argp)
{ {
argp = (char *) ALIGN(argp, alignment); argp = (char *) ALIGN (argp, alignment);
} }
if ((*p_arg)->type == FFI_TYPE_STRUCT) if ((*p_arg)->type == FFI_TYPE_STRUCT)
{ {
argp = (char *) ALIGN(argp, 4); argp = (char *) ALIGN (argp, 4);
} }
return argp; return argp;
} }
static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack) static size_t
ffi_put_arg (ffi_type **arg_type, void **arg, char *stack)
{ {
register char* argp = stack; register char *argp = stack;
register ffi_type **p_arg = arg_type; register ffi_type **p_arg = arg_type;
register void **p_argv = arg; register void **p_argv = arg;
register size_t z = (*p_arg)->size; register size_t z = (*p_arg)->size;
if (z < sizeof(int))
if (z < sizeof (int))
{ {
z = sizeof(int); z = sizeof (int);
switch ((*p_arg)->type) switch ((*p_arg)->type)
{ {
case FFI_TYPE_SINT8: case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
break; break;
case FFI_TYPE_UINT8: case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
break; break;
case FFI_TYPE_SINT16: case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
break; break;
case FFI_TYPE_UINT16: case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
break; break;
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
memcpy(argp, *p_argv, (*p_arg)->size); memcpy (argp, *p_argv, (*p_arg)->size);
break; break;
default: default:
FFI_ASSERT(0); FFI_ASSERT (0);
} }
} }
else if (z == sizeof(int)) else if (z == sizeof (int))
{ {
if ((*p_arg)->type == FFI_TYPE_FLOAT) if ((*p_arg)->type == FFI_TYPE_FLOAT)
*(float *) argp = *(float *)(* p_argv); *(float *) argp = *(float *) (*p_argv);
else else
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
} }
else if (z == sizeof(double) && (*p_arg)->type == FFI_TYPE_DOUBLE) else if (z == sizeof (double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
{ {
*(double *) argp = *(double *)(* p_argv); *(double *) argp = *(double *) (*p_argv);
} }
else else
{ {
memcpy(argp, *p_argv, z); memcpy (argp, *p_argv, z);
} }
return z; return z;
} }
/* ffi_prep_args is called by the assembly routine once stack space /* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments has been allocated for the function's arguments
@@ -125,7 +128,8 @@ static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack)
value is cif->vfp_used (word bitset of VFP regs used for passing value is cif->vfp_used (word bitset of VFP regs used for passing
arguments). These are only used for the VFP hard-float ABI. arguments). These are only used for the VFP hard-float ABI.
*/ */
int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space) int
ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space)
{ {
register unsigned int i; register unsigned int i;
register void **p_argv; register void **p_argv;
@@ -133,8 +137,8 @@ int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space)
register ffi_type **p_arg; register ffi_type **p_arg;
argp = stack; argp = stack;
if (ecif->cif->flags == FFI_TYPE_STRUCT)
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { {
*(void **) argp = ecif->rvalue; *(void **) argp = ecif->rvalue;
argp += 4; argp += 4;
} }
@@ -142,17 +146,17 @@ int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space)
p_argv = ecif->avalue; p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0); (i != 0); i--, p_arg++, p_argv++)
i--, p_arg++, p_argv++)
{ {
argp = ffi_align(p_arg, argp); argp = ffi_align (p_arg, argp);
argp += ffi_put_arg(p_arg, p_argv, argp); argp += ffi_put_arg (p_arg, p_argv, argp);
} }
return 0; return 0;
} }
int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space) int
ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
{ {
register unsigned int i, vi = 0; register unsigned int i, vi = 0;
register void **p_argv; register void **p_argv;
@@ -162,18 +166,18 @@ int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
char done_with_regs = 0; char done_with_regs = 0;
char is_vfp_type; char is_vfp_type;
// make sure we are using FFI_VFP /* Make sure we are using FFI_VFP. */
FFI_ASSERT(ecif->cif->abi == FFI_VFP); FFI_ASSERT (ecif->cif->abi == FFI_VFP);
/* the first 4 words on the stack are used for values passed in core /* The first 4 words on the stack are used for values
* registers. */ passed in core registers. */
regp = stack; regp = stack;
eo_regp = argp = regp + 16; eo_regp = argp = regp + 16;
/* If the function returns an FFI_TYPE_STRUCT in memory,
/* if the function returns an FFI_TYPE_STRUCT in memory, that address is that address is passed in r0 to the function. */
* passed in r0 to the function */ if (ecif->cif->flags == FFI_TYPE_STRUCT)
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { {
*(void **) regp = ecif->rvalue; *(void **) regp = ecif->rvalue;
regp += 4; regp += 4;
} }
@@ -181,57 +185,57 @@ int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
p_argv = ecif->avalue; p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0); (i != 0); i--, p_arg++, p_argv++)
i--, p_arg++, p_argv++)
{ {
is_vfp_type = vfp_type_p (*p_arg); is_vfp_type = vfp_type_p (*p_arg);
/* Allocated in VFP registers. */ /* Allocated in VFP registers. */
if(vi < ecif->cif->vfp_nargs && is_vfp_type) if (vi < ecif->cif->vfp_nargs && is_vfp_type)
{ {
char *vfp_slot = (char *)(vfp_space + ecif->cif->vfp_args[vi++]); char *vfp_slot = (char *) (vfp_space + ecif->cif->vfp_args[vi++]);
ffi_put_arg(p_arg, p_argv, vfp_slot); ffi_put_arg (p_arg, p_argv, vfp_slot);
continue; continue;
} }
/* Try allocating in core registers. */ /* Try allocating in core registers. */
else if (!done_with_regs && !is_vfp_type) else if (!done_with_regs && !is_vfp_type)
{ {
char *tregp = ffi_align(p_arg, regp); char *tregp = ffi_align (p_arg, regp);
size_t size = (*p_arg)->size; size_t size = (*p_arg)->size;
size = (size < 4)? 4 : size; // pad size = (size < 4) ? 4 : size; // pad
/* Check if there is space left in the aligned register area to place /* Check if there is space left in the aligned register
* the argument */ area to place the argument. */
if(tregp + size <= eo_regp) if (tregp + size <= eo_regp)
{ {
regp = tregp + ffi_put_arg(p_arg, p_argv, tregp); regp = tregp + ffi_put_arg (p_arg, p_argv, tregp);
done_with_regs = (regp == argp); done_with_regs = (regp == argp);
// ensure we did not write into the stack area // ensure we did not write into the stack area
FFI_ASSERT(regp <= argp); FFI_ASSERT (regp <= argp);
continue; continue;
} }
/* In case there are no arguments in the stack area yet, /* In case there are no arguments in the stack area yet,
the argument is passed in the remaining core registers and on the the argument is passed in the remaining core registers
stack. */ and on the stack. */
else if (!stack_used) else if (!stack_used)
{ {
stack_used = 1; stack_used = 1;
done_with_regs = 1; done_with_regs = 1;
argp = tregp + ffi_put_arg(p_arg, p_argv, tregp); argp = tregp + ffi_put_arg (p_arg, p_argv, tregp);
FFI_ASSERT(eo_regp < argp); FFI_ASSERT (eo_regp < argp);
continue; continue;
} }
} }
/* Base case, arguments are passed on the stack */ /* Base case, arguments are passed on the stack */
stack_used = 1; stack_used = 1;
argp = ffi_align(p_arg, argp); argp = ffi_align (p_arg, argp);
argp += ffi_put_arg(p_arg, p_argv, argp); argp += ffi_put_arg (p_arg, p_argv, argp);
} }
/* Indicate the VFP registers used. */ /* Indicate the VFP registers used. */
return ecif->cif->vfp_used; return ecif->cif->vfp_used;
} }
/* Perform machine dependent cif processing */ /* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ffi_status
ffi_prep_cif_machdep (ffi_cif * cif)
{ {
int type_code; int type_code;
/* Round the stack up to a multiple of 8 bytes. This isn't needed /* Round the stack up to a multiple of 8 bytes. This isn't needed
@@ -254,21 +258,24 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
break; break;
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
if (cif->abi == FFI_VFP if (cif->abi == FFI_VFP && (type_code = vfp_type_p (cif->rtype)) != 0)
&& (type_code = vfp_type_p (cif->rtype)) != 0)
{ {
/* A Composite Type passed in VFP registers, either /* A Composite Type passed in VFP registers, either
FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */ FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
cif->flags = (unsigned) type_code; cif->flags = (unsigned) type_code;
} }
else if (cif->rtype->size <= 4) else if (cif->rtype->size <= 4)
{
/* A Composite Type not larger than 4 bytes is returned in r0. */ /* A Composite Type not larger than 4 bytes is returned in r0. */
cif->flags = (unsigned)FFI_TYPE_INT; cif->flags = (unsigned) FFI_TYPE_INT;
}
else else
{
/* A Composite Type larger than 4 bytes, or whose size cannot /* A Composite Type larger than 4 bytes, or whose size cannot
be determined statically ... is stored in memory at an be determined statically ... is stored in memory at an
address passed [in r0]. */ address passed [in r0]. */
cif->flags = (unsigned)FFI_TYPE_STRUCT; cif->flags = (unsigned) FFI_TYPE_STRUCT;
}
break; break;
default: default:
@@ -276,9 +283,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
break; break;
} }
/* Map out the register placements of VFP register args. /* Map out the register placements of VFP register args. The VFP
The VFP hard-float calling conventions are slightly more sophisticated than hard-float calling conventions are slightly more sophisticated
the base calling conventions, so we do it here instead of in ffi_prep_args(). */ than the base calling conventions, so we do it here instead of
in ffi_prep_args(). */
if (cif->abi == FFI_VFP) if (cif->abi == FFI_VFP)
layout_vfp_args (cif); layout_vfp_args (cif);
@@ -286,22 +294,25 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
} }
/* Perform machine dependent cif processing for variadic calls */ /* Perform machine dependent cif processing for variadic calls */
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, ffi_status
unsigned int nfixedargs, ffi_prep_cif_machdep_var (ffi_cif * cif,
unsigned int ntotalargs) unsigned int nfixedargs, unsigned int ntotalargs)
{ {
/* VFP variadic calls actually use the SYSV ABI */ /* VFP variadic calls actually use the SYSV ABI */
if (cif->abi == FFI_VFP) if (cif->abi == FFI_VFP)
cif->abi = FFI_SYSV; cif->abi = FFI_SYSV;
return ffi_prep_cif_machdep(cif); return ffi_prep_cif_machdep (cif);
} }
/* Prototypes for assembly functions, in sysv.S */ /* Prototypes for assembly functions, in sysv.S. */
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); extern void ffi_call_SYSV (void (*fn) (void), extended_cif *, unsigned,
extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, 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) void
ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
{ {
extended_cif ecif; extended_cif ecif;
@@ -315,20 +326,19 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ecif.cif = cif; ecif.cif = cif;
ecif.avalue = avalue; ecif.avalue = avalue;
/* If the return value is a struct and we don't have a return */ /* If the return value is a struct and we don't have a return
/* value address then we need to make one */ value address then we need to make one. */
if ((rvalue == NULL) && if ((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT))
(cif->flags == FFI_TYPE_STRUCT))
{ {
ecif.rvalue = alloca(cif->rtype->size); ecif.rvalue = alloca (cif->rtype->size);
} }
else if (small_struct) else if (small_struct)
ecif.rvalue = &temp; ecif.rvalue = &temp;
else if (vfp_struct) else if (vfp_struct)
{ {
/* Largest case is double x 4. */ /* Largest case is double x 4. */
ecif.rvalue = alloca(32); ecif.rvalue = alloca (32);
} }
else else
ecif.rvalue = rvalue; ecif.rvalue = rvalue;
@@ -346,30 +356,30 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
#endif #endif
default: default:
FFI_ASSERT(0); FFI_ASSERT (0);
break; break;
} }
if (small_struct) if (small_struct)
{ {
FFI_ASSERT(rvalue != NULL); FFI_ASSERT (rvalue != NULL);
memcpy (rvalue, &temp, cif->rtype->size); memcpy (rvalue, &temp, cif->rtype->size);
} }
else if (vfp_struct) else if (vfp_struct)
{ {
FFI_ASSERT(rvalue != NULL); FFI_ASSERT (rvalue != NULL);
memcpy (rvalue, ecif.rvalue, cif->rtype->size); memcpy (rvalue, ecif.rvalue, cif->rtype->size);
} }
} }
/** private members **/ /** private members **/
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
void** args, ffi_cif* cif, float *vfp_stack); void **args, ffi_cif *cif,
float *vfp_stack);
static void ffi_prep_incoming_args_VFP (char *stack, void **ret, static void ffi_prep_incoming_args_VFP (char *stack, void **ret,
void** args, ffi_cif* cif, float *vfp_stack); void **args, ffi_cif *cif,
float *vfp_stack);
void ffi_closure_SYSV (ffi_closure *); void ffi_closure_SYSV (ffi_closure *);
@@ -386,7 +396,7 @@ ffi_closure_inner (ffi_closure *closure,
void **arg_area; void **arg_area;
cif = closure->cif; cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void*)); arg_area = (void **) alloca (cif->nargs * sizeof (void *));
/* this call will initialize ARG_AREA, such that each /* this call will initialize ARG_AREA, such that each
* element in that array points to the corresponding * element in that array points to the corresponding
@@ -394,9 +404,9 @@ ffi_closure_inner (ffi_closure *closure,
* a structure, it will re-set RESP to point to the * a structure, it will re-set RESP to point to the
* structure return address. */ * structure return address. */
if (cif->abi == FFI_VFP) if (cif->abi == FFI_VFP)
ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args); ffi_prep_incoming_args_VFP (args, respp, arg_area, cif, vfp_args);
else else
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); ffi_prep_incoming_args_SYSV (args, respp, arg_area, cif, vfp_args);
(closure->fun) (cif, *respp, arg_area, closure->user_data); (closure->fun) (cif, *respp, arg_area, closure->user_data);
@@ -405,7 +415,7 @@ ffi_closure_inner (ffi_closure *closure,
/*@-exportheader@*/ /*@-exportheader@*/
static void static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, ffi_prep_incoming_args_SYSV (char *stack, void **rvalue,
void **avalue, ffi_cif *cif, void **avalue, ffi_cif *cif,
/* Used only under VFP hard-float ABI. */ /* Used only under VFP hard-float ABI. */
float *vfp_stack) float *vfp_stack)
@@ -418,7 +428,8 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
argp = stack; argp = stack;
if ( cif->flags == FFI_TYPE_STRUCT ) { if (cif->flags == FFI_TYPE_STRUCT)
{
*rvalue = *(void **) argp; *rvalue = *(void **) argp;
argp += 4; argp += 4;
} }
@@ -429,13 +440,13 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
{ {
size_t z; size_t z;
argp = ffi_align(p_arg, argp); argp = ffi_align (p_arg, argp);
z = (*p_arg)->size; z = (*p_arg)->size;
/* because we're little endian, this is what it turns into. */ /* because we're little endian, this is what it turns into. */
*p_argv = (void*) argp; *p_argv = (void *) argp;
p_argv++; p_argv++;
argp += z; argp += z;
@@ -446,8 +457,8 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
/*@-exportheader@*/ /*@-exportheader@*/
static void static void
ffi_prep_incoming_args_VFP(char *stack, void **rvalue, ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
void **avalue, ffi_cif *cif, void **avalue, ffi_cif * cif,
/* Used only under VFP hard-float ABI. */ /* Used only under VFP hard-float ABI. */
float *vfp_stack) float *vfp_stack)
/*@=exportheader@*/ /*@=exportheader@*/
@@ -460,11 +471,12 @@ ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
char stack_used = 0; char stack_used = 0;
char is_vfp_type; char is_vfp_type;
FFI_ASSERT(cif->abi == FFI_VFP); FFI_ASSERT (cif->abi == FFI_VFP);
regp = stack; regp = stack;
eo_regp = argp = regp + 16; eo_regp = argp = regp + 16;
if ( cif->flags == FFI_TYPE_STRUCT ) { if (cif->flags == FFI_TYPE_STRUCT)
{
*rvalue = *(void **) regp; *rvalue = *(void **) regp;
regp += 4; regp += 4;
} }
@@ -476,39 +488,39 @@ ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
size_t z; size_t z;
is_vfp_type = vfp_type_p (*p_arg); is_vfp_type = vfp_type_p (*p_arg);
if(vi < cif->vfp_nargs && is_vfp_type) if (vi < cif->vfp_nargs && is_vfp_type)
{ {
*p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]); *p_argv++ = (void *) (vfp_stack + cif->vfp_args[vi++]);
continue; continue;
} }
else if (!done_with_regs && !is_vfp_type) else if (!done_with_regs && !is_vfp_type)
{ {
char* tregp = ffi_align(p_arg, regp); char *tregp = ffi_align (p_arg, regp);
z = (*p_arg)->size; z = (*p_arg)->size;
z = (z < 4)? 4 : z; // pad z = (z < 4) ? 4 : z; // pad
/* if the arguments either fits into the registers or uses registers /* if the arguments either fits into the registers or uses registers
* and stack, while we haven't read other things from the stack */ * and stack, while we haven't read other things from the stack */
if(tregp + z <= eo_regp || !stack_used) if (tregp + z <= eo_regp || !stack_used)
{ {
/* because we're little endian, this is what it turns into. */ /* because we're little endian, this is what it turns into. */
*p_argv = (void*) tregp; *p_argv = (void *) tregp;
p_argv++; p_argv++;
regp = tregp + z; regp = tregp + z;
// if we read past the last core register, make sure we have not read // if we read past the last core register, make sure we have not read
// from the stack before and continue reading after regp // from the stack before and continue reading after regp
if(regp > eo_regp) if (regp > eo_regp)
{ {
if(stack_used) if (stack_used)
{ {
abort(); // we should never read past the end of the register abort (); // we should never read past the end of the register
// are if the stack is already in use // are if the stack is already in use
} }
argp = regp; argp = regp;
} }
if(regp >= eo_regp) if (regp >= eo_regp)
{ {
done_with_regs = 1; done_with_regs = 1;
stack_used = 1; stack_used = 1;
@@ -518,13 +530,13 @@ ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
} }
stack_used = 1; stack_used = 1;
argp = ffi_align(p_arg, argp); argp = ffi_align (p_arg, argp);
z = (*p_arg)->size; z = (*p_arg)->size;
/* because we're little endian, this is what it turns into. */ /* because we're little endian, this is what it turns into. */
*p_argv = (void*) argp; *p_argv = (void *) argp;
p_argv++; p_argv++;
argp += z; argp += z;
@@ -549,7 +561,8 @@ extern void *ffi_closure_trampoline_table_page;
typedef struct ffi_trampoline_table ffi_trampoline_table; typedef struct ffi_trampoline_table ffi_trampoline_table;
typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry; typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
struct ffi_trampoline_table { struct ffi_trampoline_table
{
/* contiguous writable and executable pages */ /* contiguous writable and executable pages */
vm_address_t config_page; vm_address_t config_page;
vm_address_t trampoline_page; vm_address_t trampoline_page;
@@ -563,8 +576,9 @@ struct ffi_trampoline_table {
ffi_trampoline_table *next; ffi_trampoline_table *next;
}; };
struct ffi_trampoline_table_entry { struct ffi_trampoline_table_entry
void *(*trampoline)(); {
void *(*trampoline) ();
ffi_trampoline_table_entry *next; ffi_trampoline_table_entry *next;
}; };
@@ -591,22 +605,29 @@ ffi_trampoline_table_alloc ()
ffi_trampoline_table *table = NULL; ffi_trampoline_table *table = NULL;
/* Loop until we can allocate two contiguous pages */ /* Loop until we can allocate two contiguous pages */
while (table == NULL) { while (table == NULL)
{
vm_address_t config_page = 0x0; vm_address_t config_page = 0x0;
kern_return_t kt; kern_return_t kt;
/* Try to allocate two pages */ /* Try to allocate two pages */
kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE); kt =
if (kt != KERN_SUCCESS) { vm_allocate (mach_task_self (), &config_page, PAGE_SIZE * 2,
fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); VM_FLAGS_ANYWHERE);
if (kt != KERN_SUCCESS)
{
fprintf (stderr, "vm_allocate() failure: %d at %s:%d\n", kt,
__FILE__, __LINE__);
break; break;
} }
/* Now drop the second half of the allocation to make room for the trampoline table */ /* Now drop the second half of the allocation to make room for the trampoline table */
vm_address_t trampoline_page = config_page+PAGE_SIZE; vm_address_t trampoline_page = config_page + PAGE_SIZE;
kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE); kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
if (kt != KERN_SUCCESS) { if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); {
fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
__FILE__, __LINE__);
break; break;
} }
@@ -614,13 +635,20 @@ ffi_trampoline_table_alloc ()
vm_prot_t cur_prot; vm_prot_t cur_prot;
vm_prot_t max_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); 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 we lost access to the destination trampoline page, drop our config allocation mapping and retry */
if (kt != KERN_SUCCESS) { if (kt != KERN_SUCCESS)
{
/* Log unexpected failures */ /* Log unexpected failures */
if (kt != KERN_NO_SPACE) { if (kt != KERN_NO_SPACE)
fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); {
fprintf (stderr, "vm_remap() failure: %d at %s:%d\n", kt,
__FILE__, __LINE__);
} }
vm_deallocate (mach_task_self (), config_page, PAGE_SIZE); vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
@@ -628,21 +656,24 @@ ffi_trampoline_table_alloc ()
} }
/* We have valid trampoline and config pages */ /* We have valid trampoline and config pages */
table = calloc (1, sizeof(ffi_trampoline_table)); table = calloc (1, sizeof (ffi_trampoline_table));
table->free_count = FFI_TRAMPOLINE_COUNT; table->free_count = FFI_TRAMPOLINE_COUNT;
table->config_page = config_page; table->config_page = config_page;
table->trampoline_page = trampoline_page; table->trampoline_page = trampoline_page;
/* Create and initialize the free list */ /* Create and initialize the free list */
table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry)); table->free_list_pool =
calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry));
uint16_t i; uint16_t i;
for (i = 0; i < table->free_count; i++) { for (i = 0; i < table->free_count; i++)
{
ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); entry->trampoline =
(void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
if (i < table->free_count - 1) if (i < table->free_count - 1)
entry->next = &table->free_list_pool[i+1]; entry->next = &table->free_list_pool[i + 1];
} }
table->free_list = table->free_list_pool; table->free_list = table->free_list_pool;
@@ -655,18 +686,20 @@ void *
ffi_closure_alloc (size_t size, void **code) ffi_closure_alloc (size_t size, void **code)
{ {
/* Create the closure */ /* Create the closure */
ffi_closure *closure = malloc(size); ffi_closure *closure = malloc (size);
if (closure == NULL) if (closure == NULL)
return NULL; return NULL;
pthread_mutex_lock(&ffi_trampoline_lock); pthread_mutex_lock (&ffi_trampoline_lock);
/* Check for an active trampoline table with available entries. */ /* Check for an active trampoline table with available entries. */
ffi_trampoline_table *table = ffi_trampoline_tables; ffi_trampoline_table *table = ffi_trampoline_tables;
if (table == NULL || table->free_list == NULL) { if (table == NULL || table->free_list == NULL)
{
table = ffi_trampoline_table_alloc (); table = ffi_trampoline_table_alloc ();
if (table == NULL) { if (table == NULL)
free(closure); {
free (closure);
return NULL; return NULL;
} }
@@ -684,7 +717,7 @@ ffi_closure_alloc (size_t size, void **code)
ffi_trampoline_tables->free_count--; ffi_trampoline_tables->free_count--;
entry->next = NULL; entry->next = NULL;
pthread_mutex_unlock(&ffi_trampoline_lock); pthread_mutex_unlock (&ffi_trampoline_lock);
/* Initialize the return values */ /* Initialize the return values */
*code = entry->trampoline; *code = entry->trampoline;
@@ -699,7 +732,7 @@ ffi_closure_free (void *ptr)
{ {
ffi_closure *closure = ptr; ffi_closure *closure = ptr;
pthread_mutex_lock(&ffi_trampoline_lock); pthread_mutex_lock (&ffi_trampoline_lock);
/* Fetch the table and entry references */ /* Fetch the table and entry references */
ffi_trampoline_table *table = closure->trampoline_table; ffi_trampoline_table *table = closure->trampoline_table;
@@ -712,7 +745,9 @@ ffi_closure_free (void *ptr)
/* If all trampolines within this table are free, and at least one other table exists, deallocate /* If all trampolines within this table are free, and at least one other table exists, deallocate
* the table */ * the table */
if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) { if (table->free_count == FFI_TRAMPOLINE_COUNT
&& ffi_trampoline_tables != table)
{
/* Remove from the list */ /* Remove from the list */
if (table->prev != NULL) if (table->prev != NULL)
table->prev->next = table->next; table->prev->next = table->next;
@@ -724,16 +759,21 @@ ffi_closure_free (void *ptr)
kern_return_t kt; kern_return_t kt;
kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE); kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
if (kt != KERN_SUCCESS) if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
__FILE__, __LINE__);
kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE); kt =
vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
if (kt != KERN_SUCCESS) if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
__FILE__, __LINE__);
/* Deallocate free list */ /* Deallocate free list */
free (table->free_list_pool); free (table->free_list_pool);
free (table); free (table);
} else if (ffi_trampoline_tables != table) { }
else if (ffi_trampoline_tables != table)
{
/* Otherwise, bump this table to the top of the list */ /* Otherwise, bump this table to the top of the list */
table->prev = NULL; table->prev = NULL;
table->next = ffi_trampoline_tables; table->next = ffi_trampoline_tables;
@@ -770,13 +810,12 @@ ffi_closure_free (void *ptr)
/* the cif must already be prep'ed */ /* the cif must already be prep'ed */
ffi_status ffi_status
ffi_prep_closure_loc (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure * closure,
ffi_cif* cif, ffi_cif * cif,
void (*fun)(ffi_cif*,void*,void**,void*), void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data, void *user_data, void *codeloc)
void *codeloc)
{ {
void (*closure_func)(ffi_closure*) = NULL; void (*closure_func) (ffi_closure *) = NULL;
if (cif->abi == FFI_SYSV) if (cif->abi == FFI_SYSV)
closure_func = &ffi_closure_SYSV; closure_func = &ffi_closure_SYSV;
@@ -788,13 +827,11 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_BAD_ABI; return FFI_BAD_ABI;
#if FFI_EXEC_TRAMPOLINE_TABLE #if FFI_EXEC_TRAMPOLINE_TABLE
void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc); void **config = FFI_TRAMPOLINE_CODELOC_CONFIG (codeloc);
config[0] = closure; config[0] = closure;
config[1] = closure_func; config[1] = closure_func;
#else #else
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ FFI_INIT_TRAMPOLINE (&closure->tramp[0], closure_func, codeloc);
closure_func, \
codeloc);
#endif #endif
closure->cif = cif; closure->cif = cif;
@@ -806,7 +843,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
/* Below are routines for VFP hard-float support. */ /* Below are routines for VFP hard-float support. */
static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum) static int
rec_vfp_type_p (ffi_type * t, int *elt, int *elnum)
{ {
switch (t->type) switch (t->type)
{ {
@@ -833,7 +871,7 @@ static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
while (*el) while (*el)
{ {
int el_elt = 0, el_elnum = 0; int el_elt = 0, el_elnum = 0;
if (! rec_vfp_type_p (*el, &el_elt, &el_elnum) if (!rec_vfp_type_p (*el, &el_elt, &el_elnum)
|| (base_elt && base_elt != el_elt) || (base_elt && base_elt != el_elt)
|| total_elnum + el_elnum > 4) || total_elnum + el_elnum > 4)
return 0; return 0;
@@ -845,12 +883,13 @@ static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
*elt = base_elt; *elt = base_elt;
return 1; return 1;
} }
default: ; default:;
} }
return 0; return 0;
} }
static int vfp_type_p (ffi_type *t) static int
vfp_type_p (ffi_type * t)
{ {
int elt, elnum; int elt, elnum;
if (rec_vfp_type_p (t, &elt, &elnum)) if (rec_vfp_type_p (t, &elt, &elnum))
@@ -869,7 +908,8 @@ static int vfp_type_p (ffi_type *t)
return 0; return 0;
} }
static int place_vfp_arg (ffi_cif *cif, ffi_type *t) static int
place_vfp_arg (ffi_cif * cif, ffi_type * t)
{ {
short reg = cif->vfp_reg_free; short reg = cif->vfp_reg_free;
int nregs = t->size / sizeof (float); int nregs = t->size / sizeof (float);
@@ -903,7 +943,7 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
cif->vfp_reg_free = reg; cif->vfp_reg_free = reg;
} }
return 0; return 0;
next_reg: ; next_reg:;
} }
// done, mark all regs as used // done, mark all regs as used
cif->vfp_reg_free = 16; cif->vfp_reg_free = 16;
@@ -911,7 +951,8 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
return 1; return 1;
} }
static void layout_vfp_args (ffi_cif *cif) static void
layout_vfp_args (ffi_cif * cif)
{ {
int i; int i;
/* Init VFP fields */ /* Init VFP fields */