/* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { int type_code; /* Round the stack up to a multiple of 8 bytes. This isn't needed everywhere, but it is on some platforms, and it doesn't harm anything when it isn't needed. */ cif->bytes = (cif->bytes + 7) & ~7; /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags = (unsigned) cif->rtype->type; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: cif->flags = (unsigned) FFI_TYPE_SINT64; break; case FFI_TYPE_STRUCT: if (cif->abi == FFI_VFP && (type_code = vfp_type_p (cif->rtype)) != 0) { /* A Composite Type passed in VFP registers, either FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */ cif->flags = (unsigned) type_code; } else if (cif->rtype->size <= 4) /* A Composite Type not larger than 4 bytes is returned in r0. */ cif->flags = (unsigned)FFI_TYPE_INT; else /* A Composite Type larger than 4 bytes, or whose size cannot be determined statically ... is stored in memory at an address passed [in r0]. */ cif->flags = (unsigned)FFI_TYPE_STRUCT; break; default: cif->flags = FFI_TYPE_INT; break; } /* Map out the register placements of VFP register args. The VFP hard-float calling conventions are slightly more sophisticated than the base calling conventions, so we do it here instead of in ffi_prep_args(). */ if (cif->abi == FFI_VFP) layout_vfp_args (cif); return FFI_OK; }
/* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep (ffi_cif *cif) { int flags = 0, cabi = cif->abi; size_t bytes = cif->bytes; /* Map out the register placements of VFP register args. The VFP hard-float calling conventions are slightly more sophisticated than the base calling conventions, so we do it here instead of in ffi_prep_args(). */ if (cabi == FFI_VFP) layout_vfp_args (cif); /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: flags = ARM_TYPE_VOID; break; case FFI_TYPE_INT: 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: flags = ARM_TYPE_INT; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: flags = ARM_TYPE_INT64; break; case FFI_TYPE_FLOAT: flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT); break; case FFI_TYPE_DOUBLE: flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64); break; case FFI_TYPE_STRUCT: case FFI_TYPE_COMPLEX: if (cabi == FFI_VFP) { int h = vfp_type_p (cif->rtype); flags = ARM_TYPE_VFP_N; if (h == 0x100 + FFI_TYPE_FLOAT) flags = ARM_TYPE_VFP_S; if (h == 0x100 + FFI_TYPE_DOUBLE) flags = ARM_TYPE_VFP_D; if (h != 0) break; } /* A Composite Type not larger than 4 bytes is returned in r0. A Composite Type larger than 4 bytes, or whose size cannot be determined statically ... is stored in memory at an address passed [in r0]. */ if (cif->rtype->size <= 4) flags = ARM_TYPE_INT; else { flags = ARM_TYPE_STRUCT; bytes += 4; } break; default: abort(); } /* Round the stack up to a multiple of 8 bytes. This isn't needed everywhere, but it is on some platforms, and it doesn't harm anything when it isn't needed. */ bytes = ALIGN (bytes, 8); /* Minimum stack space is the 4 register arguments that we pop. */ if (bytes < 4*4) bytes = 4*4; cif->bytes = bytes; cif->flags = flags; return FFI_OK; }