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