Exemple #1
0
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. */
}
Exemple #2
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;
    }
}
Exemple #3
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;
    }
}
Exemple #4
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;
    }
}