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. */ }
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; } }
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; } }
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; } }