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); }
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); }