Back to index

python3.2  3.2.2
Defines | Functions
prep_cif.c File Reference
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>

Go to the source code of this file.

Defines

#define STACK_ARG_SIZE(x)   ALIGN(x, FFI_SIZEOF_ARG)

Functions

static ffi_status initialize_aggregate (ffi_type *arg)
ffi_status ffi_prep_cif (ffi_cif *cif, ffi_abi abi, unsigned int nargs, ffi_type *rtype, ffi_type **atypes)

Define Documentation

#define STACK_ARG_SIZE (   x)    ALIGN(x, FFI_SIZEOF_ARG)

Definition at line 31 of file prep_cif.c.


Function Documentation

ffi_status ffi_prep_cif ( ffi_cif cif,
ffi_abi  abi,
unsigned int  nargs,
ffi_type rtype,
ffi_type **  atypes 
)

Definition at line 87 of file prep_cif.c.

{
  unsigned bytes = 0;
  unsigned int i;
  ffi_type **ptr;

  FFI_ASSERT(cif != NULL);
  FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));

  cif->abi = abi;
  cif->arg_types = atypes;
  cif->nargs = nargs;
  cif->rtype = rtype;

  cif->flags = 0;

  /* Initialize the return type if necessary */
  /*@-usedef@*/
  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
    return FFI_BAD_TYPEDEF;
  /*@=usedef@*/

  /* Perform a sanity check on the return type */
  FFI_ASSERT_VALID_TYPE(cif->rtype);

  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
#if !defined M68K && !defined __x86_64__ && !defined S390
  /* Make space for the return structure pointer */
  if (cif->rtype->type == FFI_TYPE_STRUCT
      /* MSVC returns small structures in registers.  But we have a different
      workaround: pretend int32 or int64 return type, and converting to
      structure afterwards. */
#ifdef SPARC
      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
      )
    bytes = STACK_ARG_SIZE(sizeof(void*));
#endif

  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
    {

      /* Initialize any uninitialized aggregate type definitions */
      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
       return FFI_BAD_TYPEDEF;

      /* Perform a sanity check on the argument type, do this 
        check after the initialization.  */
      FFI_ASSERT_VALID_TYPE(*ptr);

#if !defined __x86_64__ && !defined S390
#ifdef SPARC
      if (((*ptr)->type == FFI_TYPE_STRUCT
          && ((*ptr)->size > 16 || cif->abi != FFI_V9))
         || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
             && cif->abi != FFI_V9))
       bytes += sizeof(void*);
      else
#endif
       {
#if !defined(_MSC_VER) && !defined(__MINGW32__)
              /* Don't know if this is a libffi bug or not.  At least on
                 Windows with MSVC, function call parameters are *not*
                 aligned in the same way as structure fields are, they are
                 only aligned in integer boundaries.

                 This doesn't do any harm for cdecl functions and closures,
                 since the caller cleans up the stack, but it is wrong for
                 stdcall functions where the callee cleans.
              */

         /* Add any padding if necessary */
         if (((*ptr)->alignment - 1) & bytes)
           bytes = ALIGN(bytes, (*ptr)->alignment);
         
#endif
         bytes += STACK_ARG_SIZE((*ptr)->size);
       }
#endif
    }

  cif->bytes = bytes;

  /* Perform machine dependent cif processing */
  return ffi_prep_cif_machdep(cif);
}

Here is the call graph for this function:

static ffi_status initialize_aggregate ( ffi_type arg) [static]

Definition at line 36 of file prep_cif.c.

{
  ffi_type **ptr; 

  FFI_ASSERT(arg != NULL);

  /*@-usedef@*/

  FFI_ASSERT(arg->elements != NULL);
  FFI_ASSERT(arg->size == 0);
  FFI_ASSERT(arg->alignment == 0);

  ptr = &(arg->elements[0]);

  while ((*ptr) != NULL)
    {
      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
       return FFI_BAD_TYPEDEF;
      
      /* Perform a sanity check on the argument type */
      FFI_ASSERT_VALID_TYPE(*ptr);

      arg->size = ALIGN(arg->size, (*ptr)->alignment);
      arg->size += (*ptr)->size;

      arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
       arg->alignment : (*ptr)->alignment;

      ptr++;
    }

  /* Structure size includes tail padding.  This is important for
     structures that fit in one register on ABIs like the PowerPC64
     Linux ABI that right justify small structs in a register.
     It's also needed for nested structure layout, for example
     struct A { long a; char b; }; struct B { struct A x; char y; };
     should find y at an offset of 2*sizeof(long) and result in a
     total size of 3*sizeof(long).  */
  arg->size = ALIGN (arg->size, arg->alignment);

  if (arg->size == 0)
    return FFI_BAD_TYPEDEF;
  else
    return FFI_OK;

  /*@=usedef@*/
}

Here is the caller graph for this function: