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