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_TYPE_LONGDOUBLE   4

Functions

void ffi_call_osf (void *, unsigned long, unsigned, void *, void(*)()) FFI_HIDDEN
void ffi_closure_osf (void)
void ffi_call (ffi_cif *cif, void(*fn)(), void *rvalue, void **avalue)
ffi_status ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
long FFI_HIDDEN ffi_closure_osf_inner (ffi_closure *closure, void *rvalue, unsigned long *argp)

Define Documentation

#define FFI_TYPE_LONGDOUBLE   4

Definition at line 38 of file ffi.c.


Function Documentation

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

Definition at line 78 of file ffi.c.

{
  unsigned long *stack, *argp;
  long i, avn;
  ffi_type **arg_types;
  
  /* 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)
    rvalue = alloca(cif->rtype->size);

  /* Allocate the space for the arguments, plus 4 words of temp
     space for ffi_call_osf.  */
  argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);

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

  i = 0;
  avn = cif->nargs;
  arg_types = cif->arg_types;

  while (i < avn)
    {
      size_t size = (*arg_types)->size;

      switch ((*arg_types)->type)
       {
       case FFI_TYPE_SINT8:
         *(SINT64 *) argp = *(SINT8 *)(* avalue);
         break;
                
       case FFI_TYPE_UINT8:
         *(SINT64 *) argp = *(UINT8 *)(* avalue);
         break;
                
       case FFI_TYPE_SINT16:
         *(SINT64 *) argp = *(SINT16 *)(* avalue);
         break;
                
       case FFI_TYPE_UINT16:
         *(SINT64 *) argp = *(UINT16 *)(* avalue);
         break;
                
       case FFI_TYPE_SINT32:
       case FFI_TYPE_UINT32:
         /* Note that unsigned 32-bit quantities are sign extended.  */
         *(SINT64 *) argp = *(SINT32 *)(* avalue);
         break;
                
       case FFI_TYPE_SINT64:
       case FFI_TYPE_UINT64:
       case FFI_TYPE_POINTER:
         *(UINT64 *) argp = *(UINT64 *)(* avalue);
         break;

       case FFI_TYPE_FLOAT:
         if (argp - stack < 6)
           {
             /* Note the conversion -- all the fp regs are loaded as
               doubles.  The in-register format is the same.  */
             *(double *) argp = *(float *)(* avalue);
           }
         else
           *(float *) argp = *(float *)(* avalue);
         break;

       case FFI_TYPE_DOUBLE:
         *(double *) argp = *(double *)(* avalue);
         break;

       case FFI_TYPE_LONGDOUBLE:
         /* 128-bit long double is passed by reference.  */
         *(long double **) argp = (long double *)(* avalue);
         size = sizeof (long double *);
         break;

       case FFI_TYPE_STRUCT:
         memcpy(argp, *avalue, (*arg_types)->size);
         break;

       default:
         FFI_ASSERT(0);
       }

      argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
      i++, arg_types++, avalue++;
    }

  ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ffi_call_osf ( void ,
unsigned  long,
unsigned  ,
void ,
void(*)()   
)

Here is the caller graph for this function:

Definition at line 43 of file ffi.c.

{
  /* Adjust cif->bytes to represent a minimum 6 words for the temporary
     register argument loading area.  */
  if (cif->bytes < 6*FFI_SIZEOF_ARG)
    cif->bytes = 6*FFI_SIZEOF_ARG;

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

    case FFI_TYPE_LONGDOUBLE:
      /* 128-bit long double is returned in memory, like a struct.  */
      cif->flags = FFI_TYPE_STRUCT;
      break;

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

Here is the caller graph for this function:

long FFI_HIDDEN ffi_closure_osf_inner ( ffi_closure *  closure,
void rvalue,
unsigned long *  argp 
)

Definition at line 204 of file ffi.c.

{
  ffi_cif *cif;
  void **avalue;
  ffi_type **arg_types;
  long i, avn, argn;

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

  argn = 0;

  /* Copy the caller's structure return address to that the closure
     returns the data directly to the caller.  */
  if (cif->flags == FFI_TYPE_STRUCT)
    {
      rvalue = (void *) argp[0];
      argn = 1;
    }

  i = 0;
  avn = cif->nargs;
  arg_types = cif->arg_types;
  
  /* Grab the addresses of the arguments from the stack frame.  */
  while (i < avn)
    {
      size_t size = arg_types[i]->size;

      switch (arg_types[i]->type)
       {
       case FFI_TYPE_SINT8:
       case FFI_TYPE_UINT8:
       case FFI_TYPE_SINT16:
       case FFI_TYPE_UINT16:
       case FFI_TYPE_SINT32:
       case FFI_TYPE_UINT32:
       case FFI_TYPE_SINT64:
       case FFI_TYPE_UINT64:
       case FFI_TYPE_POINTER:
       case FFI_TYPE_STRUCT:
         avalue[i] = &argp[argn];
         break;

       case FFI_TYPE_FLOAT:
         if (argn < 6)
           {
             /* Floats coming from registers need conversion from double
                back to float format.  */
             *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
             avalue[i] = &argp[argn - 6];
           }
         else
           avalue[i] = &argp[argn];
         break;

       case FFI_TYPE_DOUBLE:
         avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
         break;

       case FFI_TYPE_LONGDOUBLE:
         /* 128-bit long double is passed by reference.  */
         avalue[i] = (long double *) argp[argn];
         size = sizeof (long double *);
         break;

       default:
         abort ();
       }

      argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
      i++;
    }

  /* Invoke the closure.  */
  closure->fun (cif, rvalue, avalue, closure->user_data);

  /* Tell ffi_closure_osf how to perform return type promotions.  */
  return cif->rtype->type;
}
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 172 of file ffi.c.

{
  unsigned int *tramp;

  tramp = (unsigned int *) &closure->tramp[0];
  tramp[0] = 0x47fb0401;    /* mov $27,$1        */
  tramp[1] = 0xa77b0010;    /* ldq $27,16($27)   */
  tramp[2] = 0x6bfb0000;    /* jmp $31,($27),0   */
  tramp[3] = 0x47ff041f;    /* nop               */
  *(void **) &tramp[4] = ffi_closure_osf;

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

  /* Flush the Icache.

     Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
     instead, since both Compaq as and gas can handle it.

     0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>.  */
  asm volatile ("call_pal 0x86" : : : "memory");

  return FFI_OK;
}

Here is the call graph for this function: