summaryrefslogtreecommitdiffstats
path: root/js/src/ctypes/libffi/src/prep_cif.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/ctypes/libffi/src/prep_cif.c')
-rw-r--r--js/src/ctypes/libffi/src/prep_cif.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/js/src/ctypes/libffi/src/prep_cif.c b/js/src/ctypes/libffi/src/prep_cif.c
new file mode 100644
index 0000000000..06c6544036
--- /dev/null
+++ b/js/src/ctypes/libffi/src/prep_cif.c
@@ -0,0 +1,263 @@
+/* -----------------------------------------------------------------------
+ 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
+ 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>
+
+/* Round up to FFI_SIZEOF_ARG. */
+
+#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG)
+
+/* Perform machine independent initialization of aggregate type
+ specifications. */
+
+static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets)
+{
+ ffi_type **ptr;
+
+ if (UNLIKELY(arg == NULL || arg->elements == NULL))
+ return FFI_BAD_TYPEDEF;
+
+ arg->size = 0;
+ 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), NULL) != FFI_OK)))
+ return FFI_BAD_TYPEDEF;
+
+ /* Perform a sanity check on the argument type */
+ FFI_ASSERT_VALID_TYPE(*ptr);
+
+ arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment);
+ if (offsets)
+ *offsets++ = arg->size;
+ 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 = FFI_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
+ 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. */
+
+/* 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 = ntotalargs;
+ cif->rtype = rtype;
+
+ cif->flags = 0;
+#ifdef _M_ARM64
+ cif->is_variadic = isvariadic;
+#endif
+#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, NULL) != 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 FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+ /* Make space for the return structure pointer */
+ if (cif->rtype->type == FFI_TYPE_STRUCT
+#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
+
+ 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), NULL) != 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 FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+ {
+ /* Add any padding if necessary */
+ if (((*ptr)->alignment - 1) & bytes)
+ bytes = (unsigned)FFI_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 += (unsigned int)STACK_ARG_SIZE((*ptr)->size);
+ }
+#endif
+ }
+
+ 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
+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
+
+ffi_status
+ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
+{
+ if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
+ return FFI_BAD_ABI;
+ if (struct_type->type != FFI_TYPE_STRUCT)
+ return FFI_BAD_TYPEDEF;
+
+#if HAVE_LONG_DOUBLE_VARIANT
+ ffi_prep_types (abi);
+#endif
+
+ return initialize_aggregate(struct_type, offsets);
+}