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_MIPS_STOP_HERE()   do {} while(0)
#define FIX_ARGP

Functions

static void ffi_prep_args (char *stack, extended_cif *ecif, int bytes, int flags)
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
int ffi_call_O32 (void(*)(char *, extended_cif *, int, int), extended_cif *, unsigned, unsigned, unsigned *, void(*)())
int ffi_call_N32 (void(*)(char *, extended_cif *, int, int), extended_cif *, unsigned, unsigned, unsigned *, void(*)())
void ffi_call (ffi_cif *cif, void(*fn)(), void *rvalue, void **avalue)

Define Documentation

#define FFI_MIPS_STOP_HERE ( )    do {} while(0)

Definition at line 34 of file ffi.c.

#define FIX_ARGP

Definition at line 46 of file ffi.c.


Function Documentation

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

Definition at line 492 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))
    ecif.rvalue = alloca(cif->rtype->size);
  else
    ecif.rvalue = rvalue;
    
  switch (cif->abi) 
    {
#ifdef FFI_MIPS_O32
    case FFI_O32:
    case FFI_O32_SOFT_FLOAT:
      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
                 cif->flags, ecif.rvalue, fn);
      break;
#endif

#ifdef FFI_MIPS_N32
    case FFI_N32:
    case FFI_N64:
      {
        int copy_rvalue = 0;
        void *rvalue_copy = ecif.rvalue;
        if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
          {
            /* For structures smaller than 16 bytes we clobber memory
               in 8 byte increments.  Make a copy so we don't clobber
               the callers memory outside of the struct bounds.  */
            rvalue_copy = alloca(16);
            copy_rvalue = 1;
          }
        ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
                     cif->flags, rvalue_copy, fn);
        if (copy_rvalue)
          memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
      }
      break;
#endif

    default:
      FFI_ASSERT(0);
      break;
    }
}

Here is the call graph for this function:

int ffi_call_N32 ( void(*)(char *, extended_cif *, int, int ,
extended_cif ,
unsigned  ,
unsigned  ,
unsigned *  ,
void(*)()   
)

Here is the caller graph for this function:

int ffi_call_O32 ( void(*)(char *, extended_cif *, int, int ,
extended_cif ,
unsigned  ,
unsigned  ,
unsigned *  ,
void(*)()   
)

Here is the caller graph for this function:

static void ffi_prep_args ( char *  stack,
extended_cif ecif,
int  bytes,
int  flags 
) [static]

Definition at line 53 of file ffi.c.

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

#ifdef FFI_MIPS_N32
  /* If more than 8 double words are used, the remainder go
     on the stack. We reorder stuff on the stack here to 
     support this easily. */
  if (bytes > 8 * sizeof(ffi_arg))
    argp = &stack[bytes - (8 * sizeof(ffi_arg))];
  else
    argp = stack;
#else
  argp = stack;
#endif

  memset(stack, 0, bytes);

#ifdef FFI_MIPS_N32
  if ( ecif->cif->rstruct_flag != 0 )
#else
  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
#endif  
    {
      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
      argp += sizeof(ffi_arg);
      FIX_ARGP;
    }

  p_argv = ecif->avalue;

  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
    {
      size_t z;
      unsigned int a;

      /* Align if necessary.  */
      a = (*p_arg)->alignment;
      if (a < sizeof(ffi_arg))
        a = sizeof(ffi_arg);
      
      if ((a - 1) & (unsigned long) argp)
       {
         argp = (char *) ALIGN(argp, a);
         FIX_ARGP;
       }

      z = (*p_arg)->size;
      if (z <= sizeof(ffi_arg))
       {
          int type = (*p_arg)->type;
         z = sizeof(ffi_arg);

          /* The size of a pointer depends on the ABI */
          if (type == FFI_TYPE_POINTER)
            type =
              (ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;

         switch (type)
           {
             case FFI_TYPE_SINT8:
              *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
              break;

             case FFI_TYPE_UINT8:
              *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
              break;
                
             case FFI_TYPE_SINT16:
              *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
              break;
                
             case FFI_TYPE_UINT16:
              *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
              break;
                
             case FFI_TYPE_SINT32:
              *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
              break;
                
             case FFI_TYPE_UINT32:
              *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
              break;

             /* This can only happen with 64bit slots.  */
             case FFI_TYPE_FLOAT:
              *(float *) argp = *(float *)(* p_argv);
              break;

             /* Handle structures.  */
             default:
              memcpy(argp, *p_argv, (*p_arg)->size);
              break;
           }
       }
      else
       {
#ifdef FFI_MIPS_O32
         memcpy(argp, *p_argv, z);
#else
         {
           unsigned long end = (unsigned long) argp + z;
           unsigned long cap = (unsigned long) stack + bytes;

           /* Check if the data will fit within the register space.
              Handle it if it doesn't.  */

           if (end <= cap)
             memcpy(argp, *p_argv, z);
           else
             {
              unsigned long portion = cap - (unsigned long)argp;

              memcpy(argp, *p_argv, portion);
              argp = stack;
                z -= portion;
              memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
                       z);
             }
         }
#endif
      }
      p_argv++;
      argp += z;
      FIX_ARGP;
    }
}
ffi_status ffi_prep_cif_machdep ( ffi_cif *  cif)

Definition at line 278 of file ffi.c.

{
  cif->flags = 0;

#ifdef FFI_MIPS_O32
  /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
   * does not have special handling for floating point args.
   */

  if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
    {
      if (cif->nargs > 0)
       {
         switch ((cif->arg_types)[0]->type)
           {
           case FFI_TYPE_FLOAT:
           case FFI_TYPE_DOUBLE:
             cif->flags += (cif->arg_types)[0]->type;
             break;
             
           default:
             break;
           }

         if (cif->nargs > 1)
           {
             /* Only handle the second argument if the first
               is a float or double. */
             if (cif->flags)
              {
                switch ((cif->arg_types)[1]->type)
                  {
                  case FFI_TYPE_FLOAT:
                  case FFI_TYPE_DOUBLE:
                    cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
                    break;
                    
                  default:
                    break;
                  }
              }
           }
       }
    }
      
  /* Set the return type flag */

  if (cif->abi == FFI_O32_SOFT_FLOAT)
    {
      switch (cif->rtype->type)
        {
        case FFI_TYPE_VOID:
        case FFI_TYPE_STRUCT:
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
          break;

        case FFI_TYPE_SINT64:
        case FFI_TYPE_UINT64:
        case FFI_TYPE_DOUBLE:
          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
          break;
      
        case FFI_TYPE_FLOAT:
        default:
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
          break;
        }
    }
  else
    {
      /* FFI_O32 */      
      switch (cif->rtype->type)
        {
        case FFI_TYPE_VOID:
        case FFI_TYPE_STRUCT:
        case FFI_TYPE_FLOAT:
        case FFI_TYPE_DOUBLE:
          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
          break;

        case FFI_TYPE_SINT64:
        case FFI_TYPE_UINT64:
          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
          break;
      
        default:
          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
          break;
        }
    }
#endif

#ifdef FFI_MIPS_N32
  /* Set the flags necessary for N32 processing */
  {
    unsigned arg_reg = 0;
    unsigned loc = 0;
    unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
    unsigned index = 0;

    unsigned struct_flags = 0;

    if (cif->rtype->type == FFI_TYPE_STRUCT)
      {
       struct_flags = calc_n32_return_struct_flags(cif->rtype);

       if (struct_flags == 0)
         {
           /* This means that the structure is being passed as
              a hidden argument */

           arg_reg = 1;
           count = (cif->nargs < 7) ? cif->nargs : 7;

           cif->rstruct_flag = !0;
         }
       else
           cif->rstruct_flag = 0;
      }
    else
      cif->rstruct_flag = 0;

    while (count-- > 0 && arg_reg < 8)
      {
       switch ((cif->arg_types)[index]->type)
         {
         case FFI_TYPE_FLOAT:
         case FFI_TYPE_DOUBLE:
           cif->flags +=
              ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
           arg_reg++;
           break;
          case FFI_TYPE_LONGDOUBLE:
            /* Align it.  */
            arg_reg = ALIGN(arg_reg, 2);
            /* Treat it as two adjacent doubles.  */
           cif->flags +=
              (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
            arg_reg++;
           cif->flags +=
              (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
            arg_reg++;
            break;

         case FFI_TYPE_STRUCT:
            loc = arg_reg * FFI_SIZEOF_ARG;
           cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
                                          &loc, &arg_reg);
           break;

         default:
           arg_reg++;
            break;
         }

       index++;
      }

  /* Set the return type flag */
    switch (cif->rtype->type)
      {
      case FFI_TYPE_STRUCT:
       {
         if (struct_flags == 0)
           {
             /* The structure is returned through a hidden
               first argument. Do nothing, 'cause FFI_TYPE_VOID 
               is 0 */
           }
         else
           {
             /* The structure is returned via some tricky
               mechanism */
             cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
             cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
           }
         break;
       }
      
      case FFI_TYPE_VOID:
       /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
       break;
       
      case FFI_TYPE_FLOAT:
      case FFI_TYPE_DOUBLE:
       cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
       break;
      case FFI_TYPE_LONGDOUBLE:
       /* Long double is returned as if it were a struct containing
          two doubles.  */
       cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
       cif->flags += (FFI_TYPE_DOUBLE + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
                    << (4 + (FFI_FLAG_BITS * 8));
       break;
      default:
       cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
       break;
      }
  }
#endif
  
  return FFI_OK;
}

Here is the call graph for this function: