Skip to content

Commit bedbecf

Browse files
committed
Implement #78270: Support __vectorcall convention with FFI
To work around the limitation of the current rudimentary vectorcall support in our patched libffi, we forbid yet unsupported declarations, i.e. float/double parameters at certain positions (SIMD vector types and HVA types are not supported anyway).
1 parent 53b1d76 commit bedbecf

File tree

8 files changed

+349
-209
lines changed

8 files changed

+349
-209
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ PHP NEWS
1515
- FFI:
1616
. Fixed bug #78716 (Function name mangling is wrong for some parameter
1717
types). (cmb)
18+
. Implement FR #78270 (Support __vectorcall convention with FFI). (cmb)
1819

1920
- FPM:
2021
. Fixed bug #78599 (env_path_info underflow in fpm_main.c can lead to RCE).

ext/ffi/config.w32

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ if (PHP_FFI != 'no') {
1212
AC_DEFINE('HAVE_FFI_MS_CDECL', 1 ,'libffi supports ms_cdecl calling convention');
1313
AC_DEFINE('HAVE_FFI_SYSV', 1 ,'libffi supports sysv calling convention');
1414
}
15+
if (GREP_HEADER("ffitarget.h", "FFI_VECTORCALL_PARTIAL", PHP_PHP_BUILD + "\\include")) {
16+
AC_DEFINE('HAVE_FFI_VECTORCALL_PARTIAL', 1 ,'libffi partially supports vectorcall calling convention');
17+
}
1518

1619
EXTENSION('ffi', 'ffi.c ffi_parser.c', null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
1720
} else {

ext/ffi/ffi.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ static zend_always_inline int zend_ffi_zval_to_cdata(void *ptr, zend_ffi_type *t
776776
}
777777
/* }}} */
778778

779-
#if defined(ZEND_WIN32) && (defined(HAVE_FFI_FASTCALL) || defined(HAVE_FFI_STDCALL))
779+
#if defined(ZEND_WIN32) && (defined(HAVE_FFI_FASTCALL) || defined(HAVE_FFI_STDCALL) || defined(HAVE_FFI_VECTORCALL_PARTIAL))
780780
static size_t zend_ffi_arg_size(zend_ffi_type *type) /* {{{ */
781781
{
782782
zend_ffi_type *arg_type;
@@ -801,6 +801,10 @@ static zend_always_inline zend_string *zend_ffi_mangled_func_name(zend_string *n
801801
# ifdef HAVE_FFI_STDCALL
802802
case FFI_STDCALL:
803803
return strpprintf(0, "_%s@%zu", ZSTR_VAL(name), zend_ffi_arg_size(type));
804+
# endif
805+
# ifdef HAVE_FFI_VECTORCALL_PARTIAL
806+
case FFI_VECTORCALL_PARTIAL:
807+
return strpprintf(0, "%s@@%zu", ZSTR_VAL(name), zend_ffi_arg_size(type));
804808
# endif
805809
}
806810
#endif
@@ -6008,6 +6012,29 @@ void zend_ffi_make_func_type(zend_ffi_dcl *dcl, HashTable *args, zend_ffi_dcl *n
60086012
}
60096013
}
60106014

6015+
#ifdef HAVE_FFI_VECTORCALL_PARTIAL
6016+
if (dcl->abi == ZEND_FFI_ABI_VECTORCALL && args) {
6017+
zend_ulong i;
6018+
zend_ffi_type *arg_type;
6019+
6020+
ZEND_HASH_FOREACH_NUM_KEY_PTR(args, i, arg_type) {
6021+
arg_type = ZEND_FFI_TYPE(arg_type);
6022+
# ifdef _WIN64
6023+
if (i >= 4 && i <= 5 && (arg_type->kind == ZEND_FFI_TYPE_FLOAT || arg_type->kind == ZEND_FFI_TYPE_DOUBLE)) {
6024+
# else
6025+
if (i < 6 && (arg_type->kind == ZEND_FFI_TYPE_FLOAT || arg_type->kind == ZEND_FFI_TYPE_DOUBLE)) {
6026+
# endif
6027+
zend_ffi_cleanup_dcl(nested_dcl);
6028+
zend_ffi_cleanup_dcl(dcl);
6029+
zend_hash_destroy(args);
6030+
pefree(args, FFI_G(persistent));
6031+
zend_ffi_parser_error("'float'/'double' type not allowed at position " ZEND_ULONG_FMT " with __vectorcall at line %d", i+1, FFI_G(line));
6032+
return;
6033+
}
6034+
} ZEND_HASH_FOREACH_END();
6035+
}
6036+
#endif
6037+
60116038
if (zend_ffi_validate_func_ret_type(ret_type) != SUCCESS) {
60126039
zend_ffi_cleanup_dcl(nested_dcl);
60136040
zend_ffi_cleanup_dcl(dcl);
@@ -6063,6 +6090,11 @@ void zend_ffi_make_func_type(zend_ffi_dcl *dcl, HashTable *args, zend_ffi_dcl *n
60636090
case ZEND_FFI_ABI_SYSV:
60646091
type->func.abi = FFI_SYSV;
60656092
break;
6093+
#endif
6094+
#ifdef HAVE_FFI_VECTORCALL_PARTIAL
6095+
case ZEND_FFI_ABI_VECTORCALL:
6096+
type->func.abi = FFI_VECTORCALL_PARTIAL;
6097+
break;
60666098
#endif
60676099
default:
60686100
type->func.abi = FFI_DEFAULT_ABI;
@@ -6316,6 +6348,7 @@ void zend_ffi_set_abi(zend_ffi_dcl *dcl, uint16_t abi) /* {{{ */
63166348
_(stdcall) \
63176349
_(ms_abi) \
63186350
_(sysv_abi) \
6351+
_(vectorcall) \
63196352
_(aligned) \
63206353
_(packed) \
63216354
_(ms_struct) \
@@ -6381,6 +6414,9 @@ void zend_ffi_add_attribute(zend_ffi_dcl *dcl, const char *name, size_t name_len
63816414
case attr_sysv_abi:
63826415
zend_ffi_set_abi(dcl, ZEND_FFI_ABI_SYSV);
63836416
break;
6417+
case attr_vectorcall:
6418+
zend_ffi_set_abi(dcl, ZEND_FFI_ABI_VECTORCALL);
6419+
break;
63846420
case attr_aligned:
63856421
dcl->align = __BIGGEST_ALIGNMENT__;
63866422
break;

ext/ffi/ffi.g

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ declaration_specifiers(zend_ffi_dcl *dcl):
135135
{zend_ffi_set_abi(dcl, ZEND_FFI_ABI_FASTCALL);}
136136
| "__thiscall"
137137
{zend_ffi_set_abi(dcl, ZEND_FFI_ABI_THISCALL);}
138+
| "__vectorcall"
139+
{zend_ffi_set_abi(dcl, ZEND_FFI_ABI_VECTORCALL);}
138140
| "_Alignas"
139141
"("
140142
( &type_name_start

0 commit comments

Comments
 (0)