| 1 | /* -----------------------------------------------------------------------
|
|---|
| 2 | prep_cif.c - Copyright (c) 1996, 1998 Cygnus Solutions
|
|---|
| 3 |
|
|---|
| 4 | Permission is hereby granted, free of charge, to any person obtaining
|
|---|
| 5 | a copy of this software and associated documentation files (the
|
|---|
| 6 | ``Software''), to deal in the Software without restriction, including
|
|---|
| 7 | without limitation the rights to use, copy, modify, merge, publish,
|
|---|
| 8 | distribute, sublicense, and/or sell copies of the Software, and to
|
|---|
| 9 | permit persons to whom the Software is furnished to do so, subject to
|
|---|
| 10 | the following conditions:
|
|---|
| 11 |
|
|---|
| 12 | The above copyright notice and this permission notice shall be included
|
|---|
| 13 | in all copies or substantial portions of the Software.
|
|---|
| 14 |
|
|---|
| 15 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|---|
| 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|---|
| 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|---|
| 18 | IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|---|
| 19 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|---|
| 20 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|---|
| 21 | OTHER DEALINGS IN THE SOFTWARE.
|
|---|
| 22 | ----------------------------------------------------------------------- */
|
|---|
| 23 |
|
|---|
| 24 | #include <ffi.h>
|
|---|
| 25 | #include <ffi_common.h>
|
|---|
| 26 | #include <stdlib.h>
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 | /* Round up to SIZEOF_ARG. */
|
|---|
| 30 |
|
|---|
| 31 | #define STACK_ARG_SIZE(x) ALIGN(x, SIZEOF_ARG)
|
|---|
| 32 |
|
|---|
| 33 | /* Perform machine independent initialization of aggregate type
|
|---|
| 34 | specifications. */
|
|---|
| 35 |
|
|---|
| 36 | static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
|---|
| 37 | {
|
|---|
| 38 | ffi_type **ptr;
|
|---|
| 39 |
|
|---|
| 40 | FFI_ASSERT(arg != NULL);
|
|---|
| 41 |
|
|---|
| 42 | /*@-usedef@*/
|
|---|
| 43 |
|
|---|
| 44 | FFI_ASSERT(arg->elements != NULL);
|
|---|
| 45 | FFI_ASSERT(arg->size == 0);
|
|---|
| 46 | FFI_ASSERT(arg->alignment == 0);
|
|---|
| 47 |
|
|---|
| 48 | ptr = &(arg->elements[0]);
|
|---|
| 49 |
|
|---|
| 50 | while ((*ptr) != NULL)
|
|---|
| 51 | {
|
|---|
| 52 | if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
|---|
| 53 | return FFI_BAD_TYPEDEF;
|
|---|
| 54 |
|
|---|
| 55 | /* Perform a sanity check on the argument type */
|
|---|
| 56 | FFI_ASSERT(ffi_type_test((*ptr)));
|
|---|
| 57 |
|
|---|
| 58 | arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
|---|
| 59 | arg->size += (*ptr)->size;
|
|---|
| 60 |
|
|---|
| 61 | arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
|---|
| 62 | arg->alignment : (*ptr)->alignment;
|
|---|
| 63 |
|
|---|
| 64 | ptr++;
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | if (arg->size == 0)
|
|---|
| 68 | return FFI_BAD_TYPEDEF;
|
|---|
| 69 | else
|
|---|
| 70 | return FFI_OK;
|
|---|
| 71 |
|
|---|
| 72 | /*@=usedef@*/
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | /* Perform machine independent ffi_cif preparation, then call
|
|---|
| 76 | machine dependent routine. */
|
|---|
| 77 |
|
|---|
| 78 | ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
|---|
| 79 | ffi_abi abi, unsigned int nargs,
|
|---|
| 80 | /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
|---|
| 81 | /*@dependent@*/ ffi_type **atypes)
|
|---|
| 82 | {
|
|---|
| 83 | unsigned bytes = 0;
|
|---|
| 84 | unsigned int i;
|
|---|
| 85 | ffi_type **ptr;
|
|---|
| 86 |
|
|---|
| 87 | FFI_ASSERT(cif != NULL);
|
|---|
| 88 | FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi < FFI_LAST_ABI));
|
|---|
| 89 |
|
|---|
| 90 | cif->abi = abi;
|
|---|
| 91 | cif->arg_types = atypes;
|
|---|
| 92 | cif->nargs = nargs;
|
|---|
| 93 | cif->rtype = rtype;
|
|---|
| 94 |
|
|---|
| 95 | cif->flags = 0;
|
|---|
| 96 |
|
|---|
| 97 | /* Initialize the return type if necessary */
|
|---|
| 98 | /*@-usedef@*/
|
|---|
| 99 | if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
|---|
| 100 | return FFI_BAD_TYPEDEF;
|
|---|
| 101 | /*@=usedef@*/
|
|---|
| 102 |
|
|---|
| 103 | /* Perform a sanity check on the return type */
|
|---|
| 104 | FFI_ASSERT(ffi_type_test(cif->rtype));
|
|---|
| 105 |
|
|---|
| 106 | /* x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
|---|
| 107 | #if !defined M68K && !defined __x86_64__ && !defined S390
|
|---|
| 108 | /* Make space for the return structure pointer */
|
|---|
| 109 | if (cif->rtype->type == FFI_TYPE_STRUCT
|
|---|
| 110 | #ifdef SPARC
|
|---|
| 111 | && (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
|---|
| 112 | #endif
|
|---|
| 113 | )
|
|---|
| 114 | bytes = STACK_ARG_SIZE(sizeof(void*));
|
|---|
| 115 | #endif
|
|---|
| 116 |
|
|---|
| 117 | for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
|---|
| 118 | {
|
|---|
| 119 | /* Perform a sanity check on the argument type */
|
|---|
| 120 | FFI_ASSERT(ffi_type_test(*ptr));
|
|---|
| 121 |
|
|---|
| 122 | /* Initialize any uninitialized aggregate type definitions */
|
|---|
| 123 | if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
|---|
| 124 | return FFI_BAD_TYPEDEF;
|
|---|
| 125 |
|
|---|
| 126 | #if !defined __x86_64__ && !defined S390
|
|---|
| 127 | #ifdef SPARC
|
|---|
| 128 | if (((*ptr)->type == FFI_TYPE_STRUCT
|
|---|
| 129 | && ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
|---|
| 130 | || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
|---|
| 131 | && cif->abi != FFI_V9))
|
|---|
| 132 | bytes += sizeof(void*);
|
|---|
| 133 | else
|
|---|
| 134 | #endif
|
|---|
| 135 | {
|
|---|
| 136 | /* Add any padding if necessary */
|
|---|
| 137 | if (((*ptr)->alignment - 1) & bytes)
|
|---|
| 138 | bytes = ALIGN(bytes, (*ptr)->alignment);
|
|---|
| 139 |
|
|---|
| 140 | bytes += STACK_ARG_SIZE((*ptr)->size);
|
|---|
| 141 | }
|
|---|
| 142 | #endif
|
|---|
| 143 | }
|
|---|
| 144 |
|
|---|
| 145 | cif->bytes = bytes;
|
|---|
| 146 |
|
|---|
| 147 | /* Perform machine dependent cif processing */
|
|---|
| 148 | return ffi_prep_cif_machdep(cif);
|
|---|
| 149 | }
|
|---|