summaryrefslogtreecommitdiff
path: root/ext/ffi_c/libffi/src/prep_cif.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi_c/libffi/src/prep_cif.c')
-rw-r--r--ext/ffi_c/libffi/src/prep_cif.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/ext/ffi_c/libffi/src/prep_cif.c b/ext/ffi_c/libffi/src/prep_cif.c
index 8548cfd..be5eae3 100644
--- a/ext/ffi_c/libffi/src/prep_cif.c
+++ b/ext/ffi_c/libffi/src/prep_cif.c
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 2011 Anthony Green
+ prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
@@ -76,6 +76,13 @@ static ffi_status initialize_aggregate(ffi_type *arg)
total size of 3*sizeof(long). */
arg->size = ALIGN (arg->size, arg->alignment);
+ /* On some targets, the ABI defines that structures have an additional
+ alignment beyond the "natural" one based on their elements. */
+#ifdef FFI_AGGREGATE_ALIGNMENT
+ if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
+ arg->alignment = FFI_AGGREGATE_ALIGNMENT;
+#endif
+
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
else
@@ -90,38 +97,68 @@ static ffi_status initialize_aggregate(ffi_type *arg)
/* 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)
+/* For non variadic functions isvariadic should be 0 and
+ nfixedargs==ntotalargs.
+
+ For variadic calls, isvariadic should be 1 and nfixedargs
+ and ntotalargs set as appropriate. nfixedargs must always be >=1 */
+
+
+ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
+ unsigned int isvariadic,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs,
+ ffi_type *rtype, ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
+ FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
+ FFI_ASSERT(nfixedargs <= ntotalargs);
+
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
return FFI_BAD_ABI;
cif->abi = abi;
cif->arg_types = atypes;
- cif->nargs = nargs;
+ cif->nargs = ntotalargs;
cif->rtype = rtype;
cif->flags = 0;
+#if HAVE_LONG_DOUBLE_VARIANT
+ ffi_prep_types (abi);
+#endif
+
/* Initialize the return type if necessary */
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
+ if (rtype->type == FFI_TYPE_COMPLEX)
+ abort();
+#endif
/* 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
+#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
/* 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
+#ifdef TILE
+ && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
+#endif
+#ifdef XTENSA
+ && (cif->rtype->size > 16)
+#endif
+#ifdef NIOS2
+ && (cif->rtype->size > 8)
+#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
@@ -133,11 +170,15 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
+ if ((*ptr)->type == FFI_TYPE_COMPLEX)
+ abort();
+#endif
/* 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
+#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
@@ -149,7 +190,21 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
{
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
- bytes = ALIGN(bytes, (*ptr)->alignment);
+ bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment);
+
+#ifdef TILE
+ if (bytes < 10 * FFI_SIZEOF_ARG &&
+ bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
+ {
+ /* An argument is never split between the 10 parameter
+ registers and the stack. */
+ bytes = 10 * FFI_SIZEOF_ARG;
+ }
+#endif
+#ifdef XTENSA
+ if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
+ bytes = 6*4;
+#endif
bytes += STACK_ARG_SIZE((*ptr)->size);
}
@@ -159,10 +214,31 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
cif->bytes = bytes;
/* Perform machine dependent cif processing */
+#ifdef FFI_TARGET_SPECIFIC_VARIADIC
+ if (isvariadic)
+ return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
+#endif
+
return ffi_prep_cif_machdep(cif);
}
#endif /* not __CRIS__ */
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
+ ffi_type *rtype, ffi_type **atypes)
+{
+ return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
+}
+
+ffi_status ffi_prep_cif_var(ffi_cif *cif,
+ ffi_abi abi,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs,
+ ffi_type *rtype,
+ ffi_type **atypes)
+{
+ return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+}
+
#if FFI_CLOSURES
ffi_status