summaryrefslogtreecommitdiff
path: root/ext/ffi/ffi.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-03-29 02:36:55 +0300
committerDmitry Stogov <dmitry@zend.com>2019-03-29 02:36:55 +0300
commit745dd94e5585b1dd54716272dc0c37a18eaf1ee1 (patch)
treeb904156d5216bd2308217b42bc838b2d41268ee8 /ext/ffi/ffi.c
parentadf930c038c0d73f133f3e851d2bd2d827f0ebb2 (diff)
downloadphp-git-745dd94e5585b1dd54716272dc0c37a18eaf1ee1.tar.gz
Added support for more GCC extensions: attributes, __extension__, __asm__ (ignored)
Diffstat (limited to 'ext/ffi/ffi.c')
-rw-r--r--ext/ffi/ffi.c207
1 files changed, 152 insertions, 55 deletions
diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c
index 5ee1cadbf4..7b8591f0b6 100644
--- a/ext/ffi/ffi.c
+++ b/ext/ffi/ffi.c
@@ -1149,7 +1149,7 @@ static void zend_ffi_cdata_write_dim(zval *object, zval *offset, zval *value) /*
zend_throw_error(zend_ffi_exception_ce, "Cannot add next element to object of type FFI\\CData");
return;
}
-
+
dim = zval_get_long(offset);
if (EXPECTED(type->kind == ZEND_FFI_TYPE_ARRAY)) {
if (UNEXPECTED((zend_ulong)(dim) >= (zend_ulong)type->array.length)
@@ -5946,69 +5946,166 @@ void zend_ffi_set_abi(zend_ffi_dcl *dcl, uint16_t abi) /* {{{ */
# define __BIGGEST_ALIGNMENT__ sizeof(size_t)
#endif
+#define SIMPLE_ATTRIBUTES(_) \
+ _(cdecl) \
+ _(fastcall) \
+ _(thiscall) \
+ _(stdcall) \
+ _(ms_abi) \
+ _(sysv_abi) \
+ _(aligned) \
+ _(packed) \
+ _(ms_struct) \
+ _(gcc_struct) \
+ _(const) \
+ _(malloc) \
+ _(deprecated) \
+ _(nothrow) \
+ _(leaf) \
+ _(pure) \
+ _(noreturn) \
+ _(warn_unused_result)
+
+#define ATTR_ID(name) attr_ ## name,
+#define ATTR_NAME(name) {sizeof(#name)-1, #name},
+
void zend_ffi_add_attribute(zend_ffi_dcl *dcl, const char *name, size_t name_len) /* {{{ */
{
- if (name_len == sizeof("cdecl")-1 && memcmp(name, "cdecl", sizeof("cdecl")-1) == 0) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_CDECL);
- } else if (name_len == sizeof("fastcall")-1 && memcmp(name, "fastcall", sizeof("fastcall")-1) == 0) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_FASTCALL);
- } else if (name_len == sizeof("thiscall")-1 && memcmp(name, "thiscall", sizeof("thiscall")-1) == 0) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_THISCALL);
- } else if (name_len == sizeof("stdcall")-1 && memcmp(name, "stdcall", sizeof("stdcall")-1) == 0) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_STDCALL);
- } else if (name_len == sizeof("ms_abi")-1 && memcmp(name, "ms_abi", sizeof("ms_abi")-1) == 0) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_MS);
- } else if (name_len == sizeof("sysv_abi")-1 && memcmp(name, "sysv_abi", sizeof("sysv_abi")-1) == 0) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_SYSV);
- } else if (name_len == sizeof("aligned")-1 && memcmp(name, "aligned", sizeof("aligned")-1) == 0) {
- dcl->align = __BIGGEST_ALIGNMENT__;
- } else if (name_len == sizeof("packed")-1 && memcmp(name, "packed", sizeof("packed")-1) == 0) {
- dcl->attr |= ZEND_FFI_ATTR_PACKED;
- } else if (name_len == sizeof("ms_struct")-1 && memcmp(name, "ms_struct", sizeof("ms_struct")-1) == 0) {
- dcl->attr |= ZEND_FFI_ATTR_MS_STRUCT;
- } else if (name_len == sizeof("gcc_struct")-1 && memcmp(name, "gcc_struct", sizeof("gcc_struct")-1) == 0) {
- dcl->attr |= ZEND_FFI_ATTR_GCC_STRUCT;
- } else if (name_len == sizeof("const")-1 && memcmp(name, "const", sizeof("const")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("malloc")-1 && memcmp(name, "malloc", sizeof("malloc")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("deprecated")-1 && memcmp(name, "deprecated", sizeof("deprecated")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("__nothrow__")-1 && memcmp(name, "__nothrow__", sizeof("__nothrow__")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("__leaf__")-1 && memcmp(name, "__leaf__", sizeof("__leaf__")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("__malloc__")-1 && memcmp(name, "__malloc__", sizeof("__malloc__")-1) == 0) {
- /* ignore */
- } else {
- zend_ffi_parser_error("unsupported attribute '%.*s' at line %d", name_len, name, FFI_G(line));
+ enum {
+ SIMPLE_ATTRIBUTES(ATTR_ID)
+ attr_unsupported
+ };
+ static const struct {
+ size_t len;
+ const char * const name;
+ } names[] = {
+ SIMPLE_ATTRIBUTES(ATTR_NAME)
+ {0, NULL}
+ };
+ int id;
+
+ if (name_len > 4
+ && name[0] == '_'
+ && name[1] == '_'
+ && name[name_len-2] == '_'
+ && name[name_len-1] == '_') {
+ name += 2;
+ name_len -= 4;
+ }
+ for (id = 0; names[id].len != 0; id++) {
+ if (name_len == names[id].len) {
+ if (memcmp(name, names[id].name, name_len) == 0) {
+ break;
+ }
+ }
+ }
+ switch (id) {
+ case attr_cdecl:
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_CDECL);
+ break;
+ case attr_fastcall:
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_FASTCALL);
+ break;
+ case attr_thiscall:
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_THISCALL);
+ break;
+ case attr_stdcall:
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_STDCALL);
+ break;
+ case attr_ms_abi:
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_MS);
+ break;
+ case attr_sysv_abi:
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_SYSV);
+ break;
+ case attr_aligned:
+ dcl->align = __BIGGEST_ALIGNMENT__;
+ break;
+ case attr_packed:
+ dcl->attr |= ZEND_FFI_ATTR_PACKED;
+ break;
+ case attr_ms_struct:
+ dcl->attr |= ZEND_FFI_ATTR_MS_STRUCT;
+ break;
+ case attr_gcc_struct:
+ dcl->attr |= ZEND_FFI_ATTR_GCC_STRUCT;
+ break;
+ case attr_unsupported:
+ zend_ffi_parser_error("unsupported attribute '%.*s' at line %d", name_len, name, FFI_G(line));
+ break;
+ default:
+ /* ignore */
+ break;
}
}
/* }}} */
+#define VALUE_ATTRIBUTES(_) \
+ _(regparam) \
+ _(aligned) \
+ _(mode) \
+ _(nonnull) \
+ _(alloc_size) \
+ _(format) \
+ _(deprecated)
+
void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, int n, zend_ffi_val *val) /* {{{ */
{
- if (n == 0 && name_len == sizeof("regparam")-1 && memcmp(name, "regparam", sizeof("regparam")-1) == 0) {
- if ((val->kind == ZEND_FFI_VAL_INT32 || val->kind == ZEND_FFI_VAL_UINT32 || val->kind == ZEND_FFI_VAL_INT64 || val->kind == ZEND_FFI_VAL_UINT64) && val->i64 == 3) {
- zend_ffi_set_abi(dcl, ZEND_FFI_ABI_REGISTER);
- } else {
- zend_ffi_parser_error("incorrect 'regparam' value at line %d", FFI_G(line));
- }
- } else if (n == 0 && name_len == sizeof("aligned")-1 && memcmp(name, "aligned", sizeof("aligned")-1) == 0) {
- if ((val->kind == ZEND_FFI_VAL_INT32 || val->kind == ZEND_FFI_VAL_UINT32 || val->kind == ZEND_FFI_VAL_INT64 || val->kind == ZEND_FFI_VAL_UINT64)
- && val->i64 > 0 && val->i64 <= 0x80000000 && (val->i64 & (val->i64 - 1)) == 0) {
- dcl->align = val->i64;
- } else {
- zend_ffi_parser_error("incorrect 'alignemnt' value at line %d", FFI_G(line));
+ enum {
+ VALUE_ATTRIBUTES(ATTR_ID)
+ attr_unsupported
+ };
+ static const struct {
+ size_t len;
+ const char * const name;
+ } names[] = {
+ VALUE_ATTRIBUTES(ATTR_NAME)
+ {0, NULL}
+ };
+ int id;
+
+ if (name_len > 4
+ && name[0] == '_'
+ && name[1] == '_'
+ && name[name_len-2] == '_'
+ && name[name_len-1] == '_') {
+ name += 2;
+ name_len -= 4;
+ }
+ for (id = 0; names[id].len != 0; id++) {
+ if (name_len == names[id].len) {
+ if (memcmp(name, names[id].name, name_len) == 0) {
+ break;
+ }
}
- } else if (name_len == sizeof("format")-1 && memcmp(name, "format", sizeof("format")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("__format__")-1 && memcmp(name, "__format__", sizeof("__format__")-1) == 0) {
- /* ignore */
- } else if (name_len == sizeof("deprecated")-1 && memcmp(name, "deprecated", sizeof("deprecated")-1) == 0) {
- /* ignore */
- } else {
- zend_ffi_parser_error("unsupported attribute '%.*s' at line %d", name_len, name, FFI_G(line));
+ }
+ switch (id) {
+ case attr_regparam:
+ if (n == 0
+ && (val->kind == ZEND_FFI_VAL_INT32 || val->kind == ZEND_FFI_VAL_UINT32 || val->kind == ZEND_FFI_VAL_INT64 || val->kind == ZEND_FFI_VAL_UINT64)
+ && val->i64 == 3) {
+ zend_ffi_set_abi(dcl, ZEND_FFI_ABI_REGISTER);
+ } else {
+ zend_ffi_parser_error("incorrect 'regparam' value at line %d", FFI_G(line));
+ }
+ break;
+ case attr_aligned:
+ if (n == 0
+ && (val->kind == ZEND_FFI_VAL_INT32 || val->kind == ZEND_FFI_VAL_UINT32 || val->kind == ZEND_FFI_VAL_INT64 || val->kind == ZEND_FFI_VAL_UINT64)
+ && val->i64 > 0 && val->i64 <= 0x80000000 && (val->i64 & (val->i64 - 1)) == 0) {
+ dcl->align = val->i64;
+ } else {
+ zend_ffi_parser_error("incorrect 'alignemnt' value at line %d", FFI_G(line));
+ }
+ break;
+ case attr_mode:
+ // TODO: ???
+ case attr_unsupported:
+ zend_ffi_parser_error("unsupported attribute '%.*s' at line %d", name_len, name, FFI_G(line));
+ break;
+ default:
+ /* ignore */
+ break;
}
}
/* }}} */