Back to index

python3.2  3.2.2
Defines | Functions
ffi.c File Reference
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <asm/cachectl.h>

Go to the source code of this file.

Defines

#define CIF_FLAGS_INT   1
#define CIF_FLAGS_DINT   2
#define CIF_FLAGS_FLOAT   4
#define CIF_FLAGS_DOUBLE   8
#define CIF_FLAGS_LDOUBLE   16
#define CIF_FLAGS_POINTER   32
#define CIF_FLAGS_STRUCT1   64
#define CIF_FLAGS_STRUCT2   128

Functions

void ffi_call_SYSV (extended_cif *, unsigned, unsigned, void *, void(*fn)())
voidffi_prep_args (void *stack, extended_cif *ecif)
void ffi_closure_SYSV (ffi_closure *)
void ffi_closure_struct_SYSV (ffi_closure *)
unsigned int ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
void ffi_call (ffi_cif *cif, void(*fn)(), void *rvalue, void **avalue)
static void ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
ffi_status ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)

Define Documentation

#define CIF_FLAGS_DINT   2

Definition at line 99 of file ffi.c.

#define CIF_FLAGS_DOUBLE   8

Definition at line 101 of file ffi.c.

#define CIF_FLAGS_FLOAT   4

Definition at line 100 of file ffi.c.

#define CIF_FLAGS_INT   1

Definition at line 98 of file ffi.c.

#define CIF_FLAGS_LDOUBLE   16

Definition at line 102 of file ffi.c.

#define CIF_FLAGS_POINTER   32

Definition at line 103 of file ffi.c.

#define CIF_FLAGS_STRUCT1   64

Definition at line 104 of file ffi.c.

#define CIF_FLAGS_STRUCT2   128

Definition at line 105 of file ffi.c.


Function Documentation

void ffi_call ( ffi_cif cif,
void(*)()  fn,
void rvalue,
void **  avalue 
)

Definition at line 169 of file ffi.c.

{
  extended_cif ecif;

  ecif.cif = cif;
  ecif.avalue = avalue;

  /* If the return value is a struct and we don't have a return value
     address then we need to make one.  */

  if (rvalue == NULL
      && cif->rtype->type == FFI_TYPE_STRUCT
      && cif->rtype->size > 8)
    ecif.rvalue = alloca (cif->rtype->size);
  else
    ecif.rvalue = rvalue;

  switch (cif->abi)
    {
    case FFI_SYSV:
      ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
                   ecif.rvalue, fn);
      break;

    default:
      FFI_ASSERT (0);
      break;
    }
}

Here is the call graph for this function:

void ffi_call_SYSV ( extended_cif ,
unsigned  ,
unsigned  ,
void ,
void(*)()  fn 
)
void ffi_closure_struct_SYSV ( ffi_closure *  )

Here is the caller graph for this function:

void ffi_closure_SYSV ( ffi_closure *  )

Definition at line 341 of file ffi.c.

                                                           {
  ffi_cif       *cif;
  void         **arg_area;
  void          *result;
  void          *resp = &result;

  cif         = closure->cif;
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  

  /* this call will initialize ARG_AREA, such that each
   * element in that array points to the corresponding 
   * value on the stack; and if the function returns
   * a structure, it will change RESP to point to the
   * structure return address.  */

  ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
  
  (closure->fun) (cif, resp, arg_area, closure->user_data);

  /* The result is returned in rax.  This does the right thing for
     result types except for floats; we have to 'mov xmm0, rax' in the
     caller to correct this.
     TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
  */
  return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
}

#else
unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
{
  /* our various things...  */
  ffi_cif       *cif;
  void         **arg_area;

  cif         = closure->cif;
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  

  /* this call will initialize ARG_AREA, such that each
   * element in that array points to the corresponding 
   * value on the stack; and if the function returns
   * a structure, it will change RESP to point to the
   * structure return address.  */

  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);

  (closure->fun) (cif, *respp, arg_area, closure->user_data);

  return cif->flags;
}
unsigned int ffi_closure_SYSV_inner ( ffi_closure *  closure,
void resp,
void args 
)

Definition at line 236 of file ffi.c.

{
  ffi_cif *cif;
  void **arg_area;

  cif = closure->cif;
  arg_area = (void**) alloca (cif->nargs * sizeof (void *));

  ffi_prep_incoming_args_SYSV(args, arg_area, cif);

  (closure->fun) (cif, resp, arg_area, closure->user_data);

  return cif->flags;
}

Here is the call graph for this function:

void * ffi_prep_args ( void stack,
extended_cif ecif 
)

Definition at line 28 of file ffi.c.

{
  unsigned int i;
  void **p_argv;
  char *argp;
  ffi_type **p_arg;
  void *struct_value_ptr;

  argp = stack;

  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
      && !ecif->cif->flags)
    struct_value_ptr = ecif->rvalue;
  else
    struct_value_ptr = NULL;

  p_argv = ecif->avalue;

  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
       i != 0;
       i--, p_arg++)
    {
      size_t z;

      z = (*p_arg)->size;
      if (z < sizeof (int))
       {
         switch ((*p_arg)->type)
           {
           case FFI_TYPE_SINT8:
             *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
             break;

           case FFI_TYPE_UINT8:
             *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
             break;

           case FFI_TYPE_SINT16:
             *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
             break;

           case FFI_TYPE_UINT16:
             *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
             break;

           case FFI_TYPE_STRUCT:
             memcpy (argp + sizeof (int) - z, *p_argv, z);
             break;

           default:
             FFI_ASSERT (0);
           }
         z = sizeof (int);
       }
      else
       {
         memcpy (argp, *p_argv, z);

         /* Align if necessary.  */
         if ((sizeof(int) - 1) & z)
           z = ALIGN(z, sizeof(int));
       }

      p_argv++;
      argp += z;
    }

  return struct_value_ptr;
}

Here is the call graph for this function:

Definition at line 109 of file ffi.c.

{
  /* Set the return type flag */
  switch (cif->rtype->type)
    {
    case FFI_TYPE_VOID:
      cif->flags = 0;
      break;

    case FFI_TYPE_STRUCT:
      switch (cif->rtype->size)
       {
       case 1:
         cif->flags = CIF_FLAGS_STRUCT1;
         break;
       case 2:
         cif->flags = CIF_FLAGS_STRUCT2;
         break;
       case 4:
         cif->flags = CIF_FLAGS_INT;
         break;
       case 8:
         cif->flags = CIF_FLAGS_DINT;
         break;
       default:
         cif->flags = 0;
         break;
       }
      break;

    case FFI_TYPE_FLOAT:
      cif->flags = CIF_FLAGS_FLOAT;
      break;

    case FFI_TYPE_DOUBLE:
      cif->flags = CIF_FLAGS_DOUBLE;
      break;

    case FFI_TYPE_LONGDOUBLE:
      cif->flags = CIF_FLAGS_LDOUBLE;
      break;

    case FFI_TYPE_POINTER:
      cif->flags = CIF_FLAGS_POINTER;
      break;

    case FFI_TYPE_SINT64:
    case FFI_TYPE_UINT64:
      cif->flags = CIF_FLAGS_DINT;
      break;

    default:
      cif->flags = CIF_FLAGS_INT;
      break;
    }

  return FFI_OK;
}
ffi_status ffi_prep_closure_loc ( ffi_closure *  closure,
ffi_cif cif,
void(*)(ffi_cif *, void *, void **, void *)  fun,
void user_data,
void codeloc 
)

Definition at line 252 of file ffi.c.

{
  FFI_ASSERT (cif->abi == FFI_SYSV);

  *(unsigned short *)closure->tramp = 0x207c;
  *(void **)(closure->tramp + 2) = codeloc;
  *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
  if (cif->rtype->type == FFI_TYPE_STRUCT
      && !cif->flags)
    *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
  else
    *(void **)(closure->tramp + 8) = ffi_closure_SYSV;

  syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
         FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);

  closure->cif  = cif;
  closure->user_data = user_data;
  closure->fun  = fun;

  return FFI_OK;
}

Here is the call graph for this function:

static void ffi_prep_incoming_args_SYSV ( char *  stack,
void **  avalue,
ffi_cif cif 
) [static]

Definition at line 200 of file ffi.c.

{
  unsigned int i;
  void **p_argv;
  char *argp;
  ffi_type **p_arg;

  argp = stack;
  p_argv = avalue;

  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
    {
      size_t z;

      z = (*p_arg)->size;
      if (z <= 4)
       {
         *p_argv = (void *) (argp + 4 - z);

         z = 4;
       }
      else
       {
         *p_argv = (void *) argp;

         /* Align if necessary */
         if ((sizeof(int) - 1) & z)
           z = ALIGN(z, sizeof(int));
       }

      p_argv++;
      argp += z;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function: