示例#1
0
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  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                     */

#ifdef X86_WIN64
  if (rvalue == NULL
      && cif->flags == FFI_TYPE_STRUCT
      && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0))
    {
      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
    }
#else
  if (rvalue == NULL
      && (cif->flags == FFI_TYPE_STRUCT
          || cif->flags == FFI_TYPE_MS_STRUCT))
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
#endif
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
#ifdef X86_WIN64
    case FFI_WIN64:
      ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
                     cif->flags, ecif.rvalue, fn);
      break;
#else
#ifndef X86_WIN32
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
                    fn);
      break;
#else
    case FFI_SYSV:
    case FFI_MS_CDECL:
#endif
    case FFI_STDCALL:
    case FFI_THISCALL:
    case FFI_FASTCALL:
    case FFI_PASCAL:
    case FFI_REGISTER:
      ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
                     ecif.rvalue, fn);
      break;
#endif
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#2
0
void
ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
{
  extended_cif ecif;

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

  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, &ecif, cif->bytes,
		     cif->flags, ecif.rvalue, fn);
      break;
    default:
      FFI_ASSERT (0);
      break;
    }
}
示例#3
0
void
ffi_call(ffi_cif *cif,
	 void (*fn)(void),
	 void *rvalue,
	 void **avalue)
{
  int ret_type = cif->flags;
  extended_cif ecif;
 
  ecif.cif    = cif;
  ecif.avalue = avalue;
  ecif.rvalue = rvalue;

  /* If we don't have a return value, we need to fake one.  */
  if (rvalue == NULL)
    {
      if (ret_type == FFI390_RET_STRUCT)
	ecif.rvalue = alloca (cif->rtype->size);
      else
	ret_type = FFI390_RET_VOID;
    } 

  switch (cif->abi)
    {
      case FFI_SYSV:
        ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
		       ret_type, ecif.rvalue, fn);
        break;
 
      default:
        FFI_ASSERT (0);
        break;
    }
}
示例#4
0
void
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
{
  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;
    }
}
示例#5
0
文件: ffi.c 项目: enyst/plexnet
int
ffi_call(/*@dependent@*/ ffi_cif *cif, 
	 void (*fn)(), 
	 /*@out@*/ void *rvalue, 
	 /*@dependent@*/ void **avalue)
{
  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))
    {
      /*@-sysunrecog@*/
      ecif.rvalue = alloca(cif->rtype->size);
      /*@=sysunrecog@*/
    }
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
#if !defined(_WIN64)
    case FFI_SYSV:
      /*@-usedef@*/
      return ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
			   cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;

    case FFI_STDCALL:
      /*@-usedef@*/
      return ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
			      cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
#else
    case FFI_SYSV:
      /*@-usedef@*/
      /* Function call needs at least 40 bytes stack size, on win64 AMD64 */
      return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes ? cif->bytes : 40,
			   cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
#endif

    default:
      FFI_ASSERT(0);
      break;
    }
  return -1; /* theller: Hrm. */
}
示例#6
0
文件: ffi.c 项目: 5432935/crossbridge
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
{
  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) 
    {
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
		    cif->flags, ecif.rvalue, fn);
      if (cif->rtype->type == FFI_TYPE_STRUCT)
	{
	  int size = cif->rtype->size;
	  int align = cif->rtype->alignment;

	  if (size < 4)
	    {
	      if (align == 1)
	        *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
	    }
	  else if (4 < size && size < 8)
	    {
	      if (align == 1)
		{
		  memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
		}
	      else if (align == 2)
		{
		  if (size & 1)
		    size += 1;

		  if (size != 8)
		    memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
		}
	    }
	}
      break;

    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#7
0
文件: ffi.c 项目: xen0n/cpython64-64
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  /*
   * The final SYSV ABI says that structures smaller or equal 8 bytes
   * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
   * in memory.
   *
   * Just to keep things simple for the assembly code, we will always
   * bounce-buffer struct return values less than or equal to 8 bytes.
   * This allows the ASM to handle SYSV small structures by directly
   * writing r3 and r4 to memory without worrying about struct size.
   */
  unsigned int smst_buffer[2];
  extended_cif ecif;
  unsigned int rsize = 0;

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

  /* Ensure that we have a valid struct return value */
  ecif.rvalue = rvalue;
  if (cif->rtype->type == FFI_TYPE_STRUCT) {
    rsize = cif->rtype->size;
    if (rsize <= 8)
      ecif.rvalue = smst_buffer;
    else if (!rvalue)
      ecif.rvalue = alloca(rsize);
  }

  switch (cif->abi)
    {
#ifndef POWERPC64
# ifndef __NO_FPRS__
    case FFI_SYSV:
    case FFI_GCC_SYSV:
    case FFI_LINUX:
# endif
    case FFI_LINUX_SOFT_FLOAT:
      ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
      break;
#else
    case FFI_LINUX64:
      ffi_call_LINUX64 (&ecif, -(REALLYLONG) cif->bytes, cif->flags, ecif.rvalue, fn);
      break;
#endif
    default:
      FFI_ASSERT (0);
      break;
    }

  /* Check for a bounce-buffered return value */
  if (rvalue && ecif.rvalue == smst_buffer)
    memcpy(rvalue, smst_buffer, rsize);
}
示例#8
0
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  /* The final SYSV ABI says that structures smaller or equal 8 bytes
     are returned in r3/r4.  A draft ABI used by linux instead returns
     them in memory.

     We bounce-buffer SYSV small struct return values so that sysv.S
     can write r3 and r4 to memory without worrying about struct size.
   
     For ELFv2 ABI, use a bounce buffer for homogeneous structs too,
     for similar reasons.  */
  unsigned long smst_buffer[8];
  extended_cif ecif;

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

  ecif.rvalue = rvalue;
  if ((cif->flags & FLAG_RETURNS_SMST) != 0)
      ecif.rvalue = smst_buffer;
  /* Ensure that we have a valid struct return value.
     FIXME: Isn't this just papering over a user problem?  */
  else if (!rvalue && cif->rtype->type == FFI_TYPE_STRUCT)
    ecif.rvalue = alloca (cif->rtype->size);

#ifdef POWERPC64
      ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
#else
  ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
#endif

  /* Check for a bounce-buffered return value */
  if (rvalue && ecif.rvalue == smst_buffer)
    {
      unsigned int rsize = cif->rtype->size;
#ifndef __LITTLE_ENDIAN__
      /* The SYSV ABI returns a structure of up to 4 bytes in size
	 left-padded in r3.  */
# ifndef POWERPC64
      if (rsize <= 4)
	memcpy (rvalue, (char *) smst_buffer + 4 - rsize, rsize);
      else
# endif
	/* The SYSV ABI returns a structure of up to 8 bytes in size
	   left-padded in r3/r4, and the ELFv2 ABI similarly returns a
	   structure of up to 8 bytes in size left-padded in r3.  */
	if (rsize <= 8)
	  memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize);
	else
#endif
	  memcpy (rvalue, smst_buffer, rsize);
    }
}
示例#9
0
文件: ffi.c 项目: 3l13/APE_Server
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  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                     */

#ifdef X86_WIN64
  if (rvalue == NULL
      && cif->flags == FFI_TYPE_STRUCT
      && cif->rtype->size != 1 && cif->rtype->size != 2
      && cif->rtype->size != 4 && cif->rtype->size != 8)
    {
      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
    }
#else
  if (rvalue == NULL
      && cif->flags == FFI_TYPE_STRUCT)
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
#endif
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
#ifdef X86_WIN64
    case FFI_WIN64:
      ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
                     cif->flags, ecif.rvalue, fn);
      break;
#elif defined(X86_WIN32)
    case FFI_SYSV:
    case FFI_STDCALL:
      ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags,
                     ecif.rvalue, fn);
      break;
#else
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
                    fn);
      break;
#endif
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#10
0
文件: ffi.c 项目: microbang/libffi
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  extended_cif ecif;

  int small_struct = (cif->flags == FFI_TYPE_INT 
		      && cif->rtype->type == FFI_TYPE_STRUCT);
  int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
		    || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);

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

  unsigned int temp;
  
  /* 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 if (small_struct)
    ecif.rvalue = &temp;
  else if (vfp_struct)
    {
      /* Largest case is double x 4. */
      ecif.rvalue = alloca(32);
    }
  else
    ecif.rvalue = rvalue;

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

    case FFI_VFP:
      ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
      break;

    default:
      FFI_ASSERT(0);
      break;
    }
  if (small_struct)
    memcpy (rvalue, &temp, cif->rtype->size);
  else if (vfp_struct)
    memcpy (rvalue, ecif.rvalue, cif->rtype->size);
}
示例#11
0
void ffi_call(/*@dependent@*/ ffi_cif *cif, 
	      void (*fn)(), 
	      /*@out@*/ void *rvalue, 
	      /*@dependent@*/ void **avalue)
{
  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) && retval_on_stack(cif->rtype))
    {
      /*@-sysunrecog@*/
      ecif.rvalue = alloca(cif->rtype->size);
      /*@=sysunrecog@*/
    }
  else
    ecif.rvalue = rvalue;

  switch (cif->abi) 
    {
    case FFI_SYSV:
      /*@-usedef@*/
      /* To avoid changing the assembly code make sure the size of the argument 
       * block is a multiple of 16. Then add 8 to compensate for local variables
       * in ffi_call_SYSV.
       */
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
		    cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
#ifdef X86_WIN32
    case FFI_STDCALL:
      /*@-usedef@*/
      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
		    cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
#endif /* X86_WIN32 */
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#12
0
void ffi_call(/*@dependent@*/ ffi_cif *cif, 
	      void (*fn)(), 
	      /*@out@*/ void *rvalue, 
	      /*@dependent@*/ void **avalue)
{
  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))
    {
      /*@-sysunrecog@*/
      ecif.rvalue = alloca(cif->rtype->size);
      /*@=sysunrecog@*/
    }
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
    case FFI_SYSV:
      /*@-usedef@*/
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
		    cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
#ifdef X86_WIN32
    case FFI_STDCALL:
      /*@-usedef@*/
      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
		    cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
#endif /* X86_WIN32 */
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#13
0
文件: ffi.c 项目: 15580056814/hue
void ffi_call(/*@dependent@*/ ffi_cif *cif, 
	      void (*fn)(), 
	      /*@out@*/ void *rvalue, 
	      /*@dependent@*/ void **avalue)
{
  extended_cif ecif;
  UINT64 trvalue;

  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 (cif->rtype->type == FFI_TYPE_STRUCT
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
    ecif.rvalue = &trvalue;
  else if ((rvalue == NULL) && 
      (cif->rtype->type == FFI_TYPE_STRUCT))
    {
      /*@-sysunrecog@*/
      ecif.rvalue = alloca(cif->rtype->size);
      /*@=sysunrecog@*/
    }
  else
    ecif.rvalue = rvalue;

  switch (cif->abi) 
    {
    case FFI_SYSV:
      /*@-usedef@*/
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
		    cif->flags, ecif.rvalue, fn);
      /*@=usedef@*/
      break;
    default:
      FFI_ASSERT(0);
      break;
    }

  if (rvalue
      && cif->rtype->type == FFI_TYPE_STRUCT
      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
    memcpy (rvalue, &trvalue, cif->rtype->size);
}
示例#14
0
文件: ffi.c 项目: 3l13/APE_Server
void
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
{
  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) 
    {
#ifdef X86_WIN32
    case FFI_SYSV:
    case FFI_STDCALL:
      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
                     ecif.rvalue, fn);
      break;
#else
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
                    ecif.rvalue, fn);
      break;
#endif
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#15
0
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  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)
    {
#ifndef POWERPC64
    case FFI_SYSV:
    case FFI_GCC_SYSV:
    case FFI_LINUX:
    case FFI_LINUX_SOFT_FLOAT:
      ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
      break;
#else
    case FFI_LINUX64:
      ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
      break;
#endif
    default:
      FFI_ASSERT (0);
      break;
    }
}
示例#16
0
文件: ffi.c 项目: alex/libffi
void
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
{
  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->flags == FFI_TYPE_STRUCT
          || cif->flags == FFI_TYPE_MS_STRUCT))
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
#ifdef X86_WIN32
    case FFI_SYSV:
    case FFI_STDCALL:
    case FFI_MS_CDECL:
      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
		     ecif.rvalue, fn);
      break;
    case FFI_THISCALL:
    case FFI_FASTCALL:
      {
	unsigned int abi = cif->abi;
	unsigned int i, passed_regs = 0;

	if (cif->flags == FFI_TYPE_STRUCT)
	  ++passed_regs;

	for (i=0; i < cif->nargs && passed_regs < 2;i++)
	  {
	    size_t sz;

	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
	      continue;
	    sz = (cif->arg_types[i]->size + 3) & ~3;
	    if (sz == 0 || sz > 4)
	      continue;
	    ++passed_regs;
	  }
	if (passed_regs < 2 && abi == FFI_FASTCALL)
	  cif->abi = abi = FFI_THISCALL;
	if (passed_regs < 1 && abi == FFI_THISCALL)
	  cif->abi = abi = FFI_STDCALL;
        ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
                       ecif.rvalue, fn);
      }
      break;
#else
    case FFI_SYSV:
      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
                    ecif.rvalue, fn);
      break;
#endif
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#17
0
/* Call a function with the provided arguments and capture the return
   value.  */
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  extended_cif ecif;

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

  switch (cif->abi)
    {
    case FFI_SYSV:
      {
        struct call_context context;
	size_t stack_bytes;

	/* Figure out the total amount of stack space we need, the
	   above call frame space needs to be 16 bytes aligned to
	   ensure correct alignment of the first object inserted in
	   that space hence the ALIGN applied to cif->bytes.*/
	stack_bytes = ALIGN(cif->bytes, 16);

	memset (&context, 0, sizeof (context));
        if (is_register_candidate (cif->rtype))
          {
            ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn);
            switch (cif->rtype->type)
              {
              case FFI_TYPE_VOID:
              case FFI_TYPE_FLOAT:
              case FFI_TYPE_DOUBLE:
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
              case FFI_TYPE_LONGDOUBLE:
#endif
              case FFI_TYPE_UINT8:
              case FFI_TYPE_SINT8:
              case FFI_TYPE_UINT16:
              case FFI_TYPE_SINT16:
              case FFI_TYPE_UINT32:
              case FFI_TYPE_SINT32:
              case FFI_TYPE_POINTER:
              case FFI_TYPE_UINT64:
              case FFI_TYPE_INT:
              case FFI_TYPE_SINT64:
		{
		  void *addr = get_basic_type_addr (cif->rtype->type,
						    &context, 0);
		  copy_basic_type (rvalue, addr, cif->rtype->type);
		  break;
		}

              case FFI_TYPE_STRUCT:
                if (is_hfa (cif->rtype))
		  {
		    int j;
		    unsigned short type = get_homogeneous_type (cif->rtype);
		    unsigned elems = element_count (cif->rtype);
		    for (j = 0; j < elems; j++)
		      {
			void *reg = get_basic_type_addr (type, &context, j);
			copy_basic_type (rvalue, reg, type);
			rvalue += get_basic_type_size (type);
		      }
		  }
                else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
                  {
                    size_t size = ALIGN (cif->rtype->size, sizeof (UINT64));
                    memcpy (rvalue, get_x_addr (&context, 0), size);
                  }
                else
                  {
                    FFI_ASSERT (0);
                  }
                break;

              default:
                FFI_ASSERT (0);
                break;
              }
          }
        else
          {
            memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64));
            ffi_call_SYSV (aarch64_prep_args, &context, &ecif,
			   stack_bytes, fn);
          }
        break;
      }

    default:
      FFI_ASSERT (0);
      break;
    }
}
示例#18
0
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
  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                     */

#ifdef X86_WIN64
  if (rvalue == NULL
      && cif->flags == FFI_TYPE_STRUCT
      && cif->rtype->size != 1 && cif->rtype->size != 2
      && cif->rtype->size != 4 && cif->rtype->size != 8)
    {
      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
    }
#else
  if (rvalue == NULL
      && cif->flags == FFI_TYPE_STRUCT)
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
#endif
  else
    ecif.rvalue = rvalue;
    
  
  switch (cif->abi) 
    {
#ifdef X86_WIN64
    case FFI_WIN64:
      {
        // Make copies of all struct arguments
        // NOTE: not sure if responsibility should be here or in caller
        unsigned int i;
        for (i=0; i < cif->nargs;i++) {
          size_t size = cif->arg_types[i]->size;
          if ((cif->arg_types[i]->type == FFI_TYPE_STRUCT
               && (size != 1 && size != 2 && size != 4 && size != 8))
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
              || cif->arg_types[i]->type == FFI_TYPE_LONGDOUBLE
#endif
              )
            {
              void *local = alloca(size);
              memcpy(local, avalue[i], size);
              avalue[i] = local;
            }
        }
        ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
                       cif->flags, ecif.rvalue, fn);
      }
      break;
#else
    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 */
#endif /* X86_WIN64 */
    default:
      FFI_ASSERT(0);
      break;
    }
}
示例#19
0
文件: ffi.c 项目: CBodenMain/libffi
static void
ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
	      void **avalue, void *closure)
{
  int flags = cif->flags;
  ffi_type *rtype = cif->rtype;
  size_t bytes, rsize, vfp_size;
  char *stack, *vfp_space, *new_rvalue;
  struct call_frame *frame;

  rsize = 0;
  if (rvalue == NULL)
    {
      /* If the return value is a struct and we don't have a return
	 value address then we need to make one.  Otherwise the return
	 value is in registers and we can ignore them.  */
      if (flags == ARM_TYPE_STRUCT)
	rsize = rtype->size;
      else
	flags = ARM_TYPE_VOID;
    }
  else if (flags == ARM_TYPE_VFP_N)
    {
      /* Largest case is double x 4. */
      rsize = 32;
    }
  else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
    rsize = 4;

  /* Largest case.  */
  vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);

  bytes = cif->bytes;
  stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);

  vfp_space = NULL;
  if (vfp_size)
    {
      vfp_space = stack;
      stack += vfp_size;
    }

  frame = (struct call_frame *)(stack + bytes);

  new_rvalue = rvalue;
  if (rsize)
    new_rvalue = (void *)(frame + 1);

  frame->rvalue = new_rvalue;
  frame->flags = flags;
  frame->closure = closure;

  if (vfp_space)
    {
      ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
      ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
    }
  else
    {
      ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
      ffi_call_SYSV (stack, frame, fn);
    }

  if (rvalue && rvalue != new_rvalue)
    memcpy (rvalue, new_rvalue, rtype->size);
}