1 /* ----------------------------------------------------------------------- 2 prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc. 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, 16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 DEALINGS IN THE SOFTWARE. 23 ----------------------------------------------------------------------- */ 24 25 #include <ffi.h> 26 #include <ffi_common.h> 27 #include <stdlib.h> 28 29 /* Round up to FFI_SIZEOF_ARG. */ 30 31 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) 32 33 /* Perform machine independent initialization of aggregate type 34 specifications. */ 35 36 static ffi_status initialize_aggregate(ffi_type *arg) 37 { 38 ffi_type **ptr; 39 40 FFI_ASSERT(arg != NULL); 41 42 FFI_ASSERT(arg->elements != NULL); 43 FFI_ASSERT(arg->size == 0); 44 FFI_ASSERT(arg->alignment == 0); 45 46 ptr = &(arg->elements[0]); 47 48 while ((*ptr) != NULL) 49 { 50 if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) 51 return FFI_BAD_TYPEDEF; 52 53 /* Perform a sanity check on the argument type */ 54 FFI_ASSERT_VALID_TYPE(*ptr); 55 56 arg->size = ALIGN(arg->size, (*ptr)->alignment); 57 arg->size += (*ptr)->size; 58 59 arg->alignment = (arg->alignment > (*ptr)->alignment) ? 60 arg->alignment : (*ptr)->alignment; 61 62 ptr++; 63 } 64 65 /* Structure size includes tail padding. This is important for 66 structures that fit in one register on ABIs like the PowerPC64 67 Linux ABI that right justify small structs in a register. 68 It's also needed for nested structure layout, for example 69 struct A { long a; char b; }; struct B { struct A x; char y; }; 70 should find y at an offset of 2*sizeof(long) and result in a 71 total size of 3*sizeof(long). */ 72 arg->size = ALIGN (arg->size, arg->alignment); 73 74 if (arg->size == 0) 75 return FFI_BAD_TYPEDEF; 76 else 77 return FFI_OK; 78 } 79 80 #ifndef __CRIS__ 81 /* The CRIS ABI specifies structure elements to have byte 82 alignment only, so it completely overrides this functions, 83 which assumes "natural" alignment and padding. */ 84 85 /* Perform machine independent ffi_cif preparation, then call 86 machine dependent routine. */ 87 88 ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, 89 ffi_type *rtype, ffi_type **atypes) 90 { 91 unsigned bytes = 0; 92 unsigned int i; 93 ffi_type **ptr; 94 95 FFI_ASSERT(cif != NULL); 96 FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); 97 98 cif->abi = abi; 99 cif->arg_types = atypes; 100 cif->nargs = nargs; 101 cif->rtype = rtype; 102 103 cif->flags = 0; 104 105 /* Initialize the return type if necessary */ 106 if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) 107 return FFI_BAD_TYPEDEF; 108 109 /* Perform a sanity check on the return type */ 110 FFI_ASSERT_VALID_TYPE(cif->rtype); 111 112 /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ 113 #if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA 114 /* Make space for the return structure pointer */ 115 if (cif->rtype->type == FFI_TYPE_STRUCT 116 #ifdef SPARC 117 && (cif->abi != FFI_V9 || cif->rtype->size > 32) 118 #endif 119 #ifdef X86_DARWIN 120 && (cif->rtype->size > 8) 121 #endif 122 ) 123 bytes = STACK_ARG_SIZE(sizeof(void*)); 124 #endif 125 126 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) 127 { 128 129 /* Initialize any uninitialized aggregate type definitions */ 130 if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) 131 return FFI_BAD_TYPEDEF; 132 133 /* Perform a sanity check on the argument type, do this 134 check after the initialization. */ 135 FFI_ASSERT_VALID_TYPE(*ptr); 136 137 #if !defined __x86_64__ && !defined S390 && !defined PA 138 #ifdef SPARC 139 if (((*ptr)->type == FFI_TYPE_STRUCT 140 && ((*ptr)->size > 16 || cif->abi != FFI_V9)) 141 || ((*ptr)->type == FFI_TYPE_LONGDOUBLE 142 && cif->abi != FFI_V9)) 143 bytes += sizeof(void*); 144 else 145 #endif 146 { 147 /* Add any padding if necessary */ 148 if (((*ptr)->alignment - 1) & bytes) 149 bytes = ALIGN(bytes, (*ptr)->alignment); 150 151 bytes += STACK_ARG_SIZE((*ptr)->size); 152 } 153 #endif 154 } 155 156 cif->bytes = bytes; 157 158 /* Perform machine dependent cif processing */ 159 return ffi_prep_cif_machdep(cif); 160 } 161 #endif /* not __CRIS__ */ 162 163 #if FFI_CLOSURES 164 165 ffi_status 166 ffi_prep_closure (ffi_closure* closure, 167 ffi_cif* cif, 168 void (*fun)(ffi_cif*,void*,void**,void*), 169 void *user_data) 170 { 171 return ffi_prep_closure_loc (closure, cif, fun, user_data, closure); 172 } 173 174 #endif 175