Back to index

plt-scheme  4.2.1
Defines | Functions
ffi.c File Reference
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>

Go to the source code of this file.

Defines

#define FFI_INIT_TRAMPOLINE(TRAMP, FUN, CTX)

Functions

void ffi_prep_args (char *stack, extended_cif *ecif)
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
void ffi_call_SYSV (void(*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void(*fn)())
void ffi_call (ffi_cif *cif, void(*fn)(), void *rvalue, void **avalue)
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, void **args, ffi_cif *cif)
 private members
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
ffi_status ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
ffi_status ffi_prep_raw_closure_loc (ffi_raw_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, ffi_raw *, void *), void *user_data, void *codeloc)
static void ffi_prep_args_raw (char *stack, extended_cif *ecif)
void ffi_raw_call (ffi_cif *cif, void(*fn)(), void *rvalue, ffi_raw *fake_avalue)

Define Documentation

#define FFI_INIT_TRAMPOLINE (   TRAMP,
  FUN,
  CTX 
)
Value:
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
   unsigned int  __fun = (unsigned int)(FUN); \
   unsigned int  __ctx = (unsigned int)(CTX); \
   unsigned int  __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
   *(unsigned char*) &__tramp[0] = 0xb8; \
   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
   *(unsigned char *)  &__tramp[5] = 0xe9; \
   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
 })

Definition at line 309 of file ffi.c.


Function Documentation

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

Definition at line 190 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->flags == FFI_TYPE_STRUCT))
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
                  fn);
      break;
#ifdef X86_WIN32
    case FFI_STDCALL:
      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
                     ecif.rvalue, fn);
      break;
#endif /* X86_WIN32 */
    default:
      FFI_ASSERT(0);
      break;
    }
}

Here is the call graph for this function:

void ffi_call_SYSV ( void(*)(char *, extended_cif *)  ,
extended_cif ,
unsigned  ,
unsigned  ,
unsigned *  ,
void(*)()  fn 
)
void FFI_HIDDEN ffi_closure_SYSV ( ffi_closure *  )

Definition at line 232 of file ffi.c.

{
  // 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 re-set 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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ffi_prep_args ( char *  stack,
extended_cif ecif 
)

Definition at line 40 of file ffi.c.

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

  argp = stack;

  if (ecif->cif->flags == FFI_TYPE_STRUCT)
    {
      *(void **) argp = ecif->rvalue;
      argp += 4;
    }

  p_argv = ecif->avalue;

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

      /* Align if necessary */
      if ((sizeof(int) - 1) & (unsigned) argp)
       argp = (char *) ALIGN(argp, sizeof(int));

      z = (*p_arg)->size;
      if (z < sizeof(int))
       {
         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_SINT32:
             *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
             break;

           case FFI_TYPE_UINT32:
             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
             break;

           case FFI_TYPE_STRUCT:
             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
             break;

           default:
             FFI_ASSERT(0);
           }
       }
      else
       {
         memcpy(argp, *p_argv, z);
       }
      p_argv++;
      argp += z;
    }
  
  return;
}
static void ffi_prep_args_raw ( char *  stack,
extended_cif ecif 
) [static]

Definition at line 381 of file ffi.c.

{
  memcpy (stack, ecif->avalue, ecif->cif->bytes);
}

Here is the caller graph for this function:

ffi_status ffi_prep_cif_machdep ( ffi_cif *  cif)

Definition at line 117 of file ffi.c.

{
  /* Set the return type flag */
  switch (cif->rtype->type)
    {
    case FFI_TYPE_VOID:
#ifdef X86
    case FFI_TYPE_STRUCT:
#endif
#if defined(X86) || defined(X86_DARWIN)
    case FFI_TYPE_UINT8:
    case FFI_TYPE_UINT16:
    case FFI_TYPE_SINT8:
    case FFI_TYPE_SINT16:
#endif

    case FFI_TYPE_SINT64:
    case FFI_TYPE_FLOAT:
    case FFI_TYPE_DOUBLE:
    case FFI_TYPE_LONGDOUBLE:
      cif->flags = (unsigned) cif->rtype->type;
      break;

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

#ifndef X86
    case FFI_TYPE_STRUCT:
      if (cif->rtype->size == 1)
        {
          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
        }
      else if (cif->rtype->size == 2)
        {
          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
        }
      else if (cif->rtype->size == 4)
        {
          cif->flags = FFI_TYPE_INT; /* same as int type */
        }
      else if (cif->rtype->size == 8)
        {
          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
        }
      else
        {
          cif->flags = FFI_TYPE_STRUCT;
        }
      break;
#endif

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

#ifdef X86_DARWIN
  cif->bytes = (cif->bytes + 15) & ~0xF;
#endif

  return FFI_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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 324 of file ffi.c.

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

  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
                     &ffi_closure_SYSV,  \
                     codeloc);
    
  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 **  ret,
void **  args,
ffi_cif *  cif 
) [static]

private members

Definition at line 268 of file ffi.c.

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

  argp = stack;

  if ( cif->flags == FFI_TYPE_STRUCT ) {
    *rvalue = *(void **) argp;
    argp += 4;
  }

  p_argv = avalue;

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

      /* Align if necessary */
      if ((sizeof(int) - 1) & (unsigned) argp) {
       argp = (char *) ALIGN(argp, sizeof(int));
      }

      z = (*p_arg)->size;

      /* because we're little endian, this is what it turns into.   */

      *p_argv = (void*) argp;

      p_argv++;
      argp += z;
    }
  
  return;
}

Here is the caller graph for this function:

ffi_status ffi_prep_raw_closure_loc ( ffi_raw_closure *  closure,
ffi_cif *  cif,
void(*)(ffi_cif *, void *, ffi_raw *, void *)  fun,
void user_data,
void codeloc 
)

Definition at line 348 of file ffi.c.

{
  int i;

  FFI_ASSERT (cif->abi == FFI_SYSV);

  // we currently don't support certain kinds of arguments for raw
  // closures.  This should be implemented by a separate assembly language
  // routine, since it would require argument processing, something we
  // don't do now for performance.

  for (i = cif->nargs-1; i >= 0; i--)
    {
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
    }
  

  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
                     codeloc);
    
  closure->cif  = cif;
  closure->user_data = user_data;
  closure->fun  = fun;

  return FFI_OK;
}
void ffi_raw_call ( ffi_cif *  cif,
void(*)()  fn,
void rvalue,
ffi_raw *  fake_avalue 
)

Definition at line 402 of file ffi.c.

{
  extended_cif ecif;
  void **avalue = (void **)fake_avalue;

  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))
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
                  ecif.rvalue, fn);
      break;
#ifdef X86_WIN32
    case FFI_STDCALL:
      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
                     ecif.rvalue, fn);
      break;
#endif /* X86_WIN32 */
    default:
      FFI_ASSERT(0);
      break;
    }
}

Here is the call graph for this function: