#include <ffi.h>
#include <ffi_common.h>
#include <stdbool.h>
#include <stdlib.h>
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
static ffi_status
initialize_aggregate(
ffi_type* arg)
{
if (arg == NULL || arg->elements == NULL ||
arg->size != 0 || arg->alignment != 0)
return FFI_BAD_TYPEDEF;
ffi_type** ptr = &(arg->elements[0]);
while ((*ptr) != NULL)
{
if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK))
return FFI_BAD_TYPEDEF;
FFI_ASSERT_VALID_TYPE(*ptr);
#ifdef POWERPC_DARWIN
int curalign = (*ptr)->alignment;
if (ptr != &(arg->elements[0]))
{
if (curalign > 4 && curalign != 16)
curalign = 4;
}
arg->size = ALIGN(arg->size, curalign);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > curalign) ?
arg->alignment : curalign;
#else
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
#endif
ptr++;
}
arg->size = ALIGN(arg->size, arg->alignment);
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
return FFI_OK;
}
#ifndef __CRIS__
#if defined(X86_DARWIN)
static inline bool
struct_on_stack(
int size)
{
if (size > 8)
return true;
switch (size)
{
case 1:
case 2:
case 4:
case 8:
return false;
default:
return true;
}
}
#endif // defined(X86_DARWIN)
ffi_status
ffi_prep_cif(
ffi_cif* cif,
ffi_abi abi,
unsigned int nargs,
ffi_type* rtype,
ffi_type** atypes)
{
if (cif == NULL)
return FFI_BAD_TYPEDEF;
if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI)
return FFI_BAD_ABI;
unsigned int bytes = 0;
unsigned int i;
ffi_type** ptr;
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->rtype = rtype;
cif->flags = 0;
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
FFI_ASSERT_VALID_TYPE(cif->rtype);
#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
#ifdef X86_DARWIN
&& (struct_on_stack(cif->rtype->size))
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
if ((*ptr)->alignment == 0)
return FFI_BAD_TYPEDEF;
FFI_ASSERT_VALID_TYPE(*ptr);
#if defined(X86_DARWIN)
{
int align = (*ptr)->alignment;
if (align > 4)
align = 4;
if ((align - 1) & bytes)
bytes = ALIGN(bytes, align);
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#elif !defined __x86_64__ && !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
{
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
cif->bytes = bytes;
return ffi_prep_cif_machdep(cif);
}
#endif