PageRenderTime 56ms CodeModel.GetById 25ms app.highlight 23ms RepoModel.GetById 2ms app.codeStats 0ms

/Modules/_ctypes/libffi_arm_wince/prep_cif.c

http://unladen-swallow.googlecode.com/
C | 175 lines | 81 code | 34 blank | 60 comment | 41 complexity | df1eabe52f38f190f7c8050fc77966f4 MD5 | raw file
  1/* -----------------------------------------------------------------------
  2   prep_cif.c - Copyright (c) 1996, 1998  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, 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 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
 36static 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_VALID_TYPE(*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  /* Structure size includes tail padding.  This is important for
 68     structures that fit in one register on ABIs like the PowerPC64
 69     Linux ABI that right justify small structs in a register.
 70     It's also needed for nested structure layout, for example
 71     struct A { long a; char b; }; struct B { struct A x; char y; };
 72     should find y at an offset of 2*sizeof(long) and result in a
 73     total size of 3*sizeof(long).  */
 74  arg->size = ALIGN (arg->size, arg->alignment);
 75
 76  if (arg->size == 0)
 77    return FFI_BAD_TYPEDEF;
 78  else
 79    return FFI_OK;
 80
 81  /*@=usedef@*/
 82}
 83
 84/* Perform machine independent ffi_cif preparation, then call
 85   machine dependent routine. */
 86
 87ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
 88			ffi_abi abi, unsigned int nargs, 
 89			/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
 90			/*@dependent@*/ ffi_type **atypes)
 91{
 92  unsigned bytes = 0;
 93  unsigned int i;
 94  ffi_type **ptr;
 95
 96  FFI_ASSERT(cif != NULL);
 97  FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
 98
 99  cif->abi = abi;
100  cif->arg_types = atypes;
101  cif->nargs = nargs;
102  cif->rtype = rtype;
103
104  cif->flags = 0;
105
106  /* Initialize the return type if necessary */
107  /*@-usedef@*/
108  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
109    return FFI_BAD_TYPEDEF;
110  /*@=usedef@*/
111
112  /* Perform a sanity check on the return type */
113  FFI_ASSERT_VALID_TYPE(cif->rtype);
114
115  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
116#if !defined M68K && !defined __x86_64__ && !defined S390
117  /* Make space for the return structure pointer */
118  if (cif->rtype->type == FFI_TYPE_STRUCT
119      /* MSVC returns small structures in registers.  But we have a different
120      workaround: pretend int32 or int64 return type, and converting to
121      structure afterwards. */
122#ifdef SPARC
123      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
124#endif
125      )
126    bytes = STACK_ARG_SIZE(sizeof(void*));
127#endif
128
129  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
130    {
131
132      /* Initialize any uninitialized aggregate type definitions */
133      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
134	return FFI_BAD_TYPEDEF;
135
136      /* Perform a sanity check on the argument type, do this 
137	 check after the initialization.  */
138      FFI_ASSERT_VALID_TYPE(*ptr);
139
140#if !defined __x86_64__ && !defined S390
141#ifdef SPARC
142      if (((*ptr)->type == FFI_TYPE_STRUCT
143	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))
144	  || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
145	      && cif->abi != FFI_V9))
146	bytes += sizeof(void*);
147      else
148#endif
149	{
150#ifndef _MSC_VER
151		/* Don't know if this is a libffi bug or not.  At least on
152		   Windows with MSVC, function call parameters are *not*
153		   aligned in the same way as structure fields are, they are
154		   only aligned in integer boundaries.
155
156		   This doesn't do any harm for cdecl functions and closures,
157		   since the caller cleans up the stack, but it is wrong for
158		   stdcall functions where the callee cleans.
159		*/
160
161	  /* Add any padding if necessary */
162	  if (((*ptr)->alignment - 1) & bytes)
163	    bytes = ALIGN(bytes, (*ptr)->alignment);
164	  
165#endif
166	  bytes += STACK_ARG_SIZE((*ptr)->size);
167	}
168#endif
169    }
170
171  cif->bytes = bytes;
172
173  /* Perform machine dependent cif processing */
174  return ffi_prep_cif_machdep(cif);
175}