From 7e3b009ddee1508720d3493c3985654e8f21ea0e Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 26 Jan 2016 08:40:37 +0100 Subject: [PATCH] struct member fixes --- m4/psi.m4 | 9 +++++++ m4/psi_struct.m4 | 22 ++++++++++++++-- m4/psi_type.m4 | 7 +++--- php_psi.h | 1 + src/context.c | 26 ++++++++++++++++++- src/libffi.c | 65 ++++++++++++++++++++++++++---------------------- src/libjit.c | 58 ++++++++++++++++++++++-------------------- src/module.c | 9 +++++++ 8 files changed, 134 insertions(+), 63 deletions(-) diff --git a/m4/psi.m4 b/m4/psi.m4 index 3853fa6..37864d0 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -164,6 +164,10 @@ AC_DEFUN([PSI_PKG_CONFIG], [ export PKG_CONFIG_PATH="$PHP_PSI_LIBFFI/lib/pkgconfig:$PHP_PSI_LIBJIT/lib/pkgconfig:$PKG_CONFIG_PATH" ]) +dnl PSI_SH_SIZEOF(type) +dnl expand to shell variable $ac_cv_sizeof_ +AC_DEFUN([PSI_SH_SIZEOF], [$AS_TR_SH([ac_cv_sizeof_]$1)]) + dnl PSI_SH_TEST_SIZEOF(type) dnl `if` condition to test if $ac_cv_sizeof_$1 is greater than 0. AC_DEFUN([PSI_SH_TEST_SIZEOF], [test -n "$AS_TR_SH([ac_cv_sizeof_]$1)" && test "$AS_TR_SH([ac_cv_sizeof_]$1)" -gt 0]) @@ -198,6 +202,11 @@ AC_DEFUN(PSI_CHECK_OFFSETOF, [ ) ]) +dnl PSI_SH_OFFSETOF(type) +dnl Expand to shell variable $ac_cv_offsetof_ +AC_DEFUN([PSI_SH_OFFSETOF], [$AS_TR_SH([ac_cv_offsetof_]$1)]) + + dnl PSI_COMPUTE_STR(variable, string or expression) dnl Compute a string constant value in a similar manner like AC_COMPUTE_INT. AC_DEFUN(PSI_COMPUTE_STR, [ diff --git a/m4/psi_struct.m4 b/m4/psi_struct.m4 index fcee59c..5a03dd5 100644 --- a/m4/psi_struct.m4 +++ b/m4/psi_struct.m4 @@ -14,8 +14,26 @@ AC_DEFUN(PSI_STRUCT_MEMBER, [ ) if PSI_SH_TEST_SIZEOF($1 member_name); then PSI_CHECK_OFFSETOF($1, member_name) - PSI_TYPE_INDIRECTION($2, [$AS_TR_SH([ac_cv_sizeof_]$1[_]member_name)], pl, as) - psi_struct_members="[$psi_struct_members, {]PSI_TYPE_PAIR(member_type)[, \"]member_name[\", $]AS_TR_SH([ac_cv_offsetof_]$1[_]member_name)[, $]AS_TR_SH([ac_cv_sizeof_]$1[_]member_name), $pl, $as[}]" + PSI_TYPE_INDIRECTION($2, [PSI_SH_SIZEOF([$1 member_name])], pl, as) + + psi_member_sizeof=PSI_SH_SIZEOF($1 member_name) + psi_member_offsetof=PSI_SH_OFFSETOF($1 member_name) + + if test $pl -gt 0 && test $as -eq 0; then + check_size=PSI_SH_SIZEOF(void *) + elif test $pl -eq 1 && test $as -gt 0; then + check_size=`expr PSI_SH_SIZEOF(member_type) \* $as` + else + check_size=PSI_SH_SIZEOF(member_type) + fi + if test $psi_member_sizeof != "$check_size"; then + psi_member_basic_type=PSI_SH_BASIC_TYPE(member_type) + psi_member_type_pair="`psi_type_pair $psi_member_basic_type $psi_member_sizeof`" + psi_struct_members="$psi_struct_members, {$psi_member_type_pair, \"[]member_name[]\", $psi_member_offsetof, $psi_member_sizeof, $pl, $as}" + AC_MSG_WARN(pre-defined size $check_size of $2 in $1 does not match computed size $psi_member_sizeof; adjusting to $psi_member_type_pair) + else + psi_struct_members="[$psi_struct_members, {]PSI_TYPE_PAIR(member_type)[, \"]member_name[\", $psi_member_offsetof, $psi_member_sizeof, $pl, $as}]" + fi fi ]) diff --git a/m4/psi_type.m4 b/m4/psi_type.m4 index 2936ef1..7e4badb 100644 --- a/m4/psi_type.m4 +++ b/m4/psi_type.m4 @@ -49,10 +49,13 @@ AC_DEFUN(PSI_TYPE, [ if test "$2" && PSI_SH_TEST_SIZEOF($1); then AS_TR_SH(psi_basic_type_$1)=$psi_basic_type psi_add_type "{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}" - #cat >>$PSI_TYPES <<<"{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, " fi ]) +dnl PSI_SH_BASIC_TYPE(type) +dnl Expand to the basic type (int/uint) of a distinct type +AC_DEFUN(PSI_SH_BASIC_TYPE, [$AS_TR_SH([psi_basic_type_]$1)]) + dnl PSI_OPAQUE_TYPE(type name) dnl Checks a type for being a scalar, a struct or a pointer type. dnl Calls AC_TYPE_ (if defined) and PSI_CHECK_SIZEOF. @@ -83,14 +86,12 @@ AC_DEFUN(PSI_OPAQUE_TYPE, [ scalar) AX_CHECK_SIGN($1, [psi_basic_type=int], [psi_basic_type=uint], PSI_INCLUDES) psi_add_type "{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}" - #cat >>$PSI_TYPES <<<" {`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, " ;; struct) PSI_STRUCT($1) ;; pointer*) psi_add_type "{PSI_T_POINTER, \"void\", \"$1\"}" - #cat >>$PSI_TYPES <<<" {PSI_T_POINTER, \"void\", \"$1\"}, " ;; *) AC_MSG_WARN(could not detect type class of $1) diff --git a/php_psi.h b/php_psi.h index 8bac826..7673d4e 100644 --- a/php_psi.h +++ b/php_psi.h @@ -46,6 +46,7 @@ size_t psi_t_alignment(token_t t); size_t psi_t_size(token_t t); size_t psi_t_align(token_t t, size_t s); +size_t psi_offset_padding(size_t diff, size_t alignment); int psi_internal_type(impl_type *type); zend_internal_arg_info *psi_internal_arginfo(impl *impl); size_t psi_num_min_args(impl *impl); diff --git a/src/context.c b/src/context.c index 3ab1d21..0242b77 100644 --- a/src/context.c +++ b/src/context.c @@ -221,7 +221,31 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) { ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg); darg->var->arg = darg; - if (!darg->layout) { + if (darg->layout) { + size_t size; + + if (darg->var->array_size) { + size = psi_t_size(real_decl_type(darg->type)->type) * darg->var->array_size; + } else if (darg->var->pointer_level) { + size = psi_t_size(PSI_T_POINTER); + } else { + decl_type *real = real_decl_type(darg->type); + + if (real->type == PSI_T_STRUCT) { + size = real->strct->size; + } else { + size = psi_t_size(real->type); + } + } + if (darg->layout->len != size) { + data->error(darg->token, PSI_WARNING, + "Computed length %zu of %s.%s does not match" + " pre-defined length %zu of type '%s'", + darg->layout->len, s->name, darg->var->name, size, + darg->type->name); + return 0; + } + } else { token_t t; if (darg->var->pointer_level && (!darg->var->array_size || darg->var->pointer_level == 1)) { diff --git a/src/libffi.c b/src/libffi.c index d59712c..5962b5e 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -127,53 +127,58 @@ static void psi_ffi_struct_type_dtor(void *type) { free(strct); } +static size_t psi_ffi_struct_type_pad(ffi_type **els, size_t padding) { + size_t i; + + for (i = 0; i < padding; ++i) { + ffi_type *pad = malloc(sizeof(*pad)); + + memcpy(pad, &ffi_type_schar, sizeof(*pad)); + *els++ = pad; + } + + return padding; +} + static ffi_type **psi_ffi_struct_type_elements(decl_struct *strct) { - size_t i, j, argc = strct->args->count << 2, nels = 0, offset = 0, align, padding; + size_t i, argc = strct->args->count, nels = 0, offset = 0, maxalign = 0; ffi_type **els = calloc(argc + 1, sizeof(*els)); for (i = 0; i < strct->args->count; ++i) { decl_arg *darg = strct->args->args[i]; ffi_type *type = malloc(sizeof(*type)); + size_t padding; memcpy(type, psi_ffi_decl_arg_type(darg), sizeof(*type)); - if (darg->layout->pos > offset) { - padding = darg->layout->pos - offset; - align = ((padding - 1) | (type->alignment - 1)) + 1; - if (align >= padding) { - padding = 0; - } - } else { - align = 0; - padding = 0; - } + ZEND_ASSERT(type->size == darg->layout->len); - if (padding) { - for (j = 0; j < padding; ++j) { - ffi_type *pad = malloc(sizeof(*pad)); + if (type->alignment > maxalign) { + maxalign = type->alignment; + } - ZEND_ASSERT(nels + 1 < argc); - memcpy(pad, &ffi_type_schar, sizeof(*pad)); - els[nels++] = pad; + if ((padding = psi_offset_padding(darg->layout->pos - offset, type->alignment))) { + if (nels + padding + 1 > argc) { + argc += padding; + els = realloc(els, (argc + 1) * sizeof(*els)); + els[argc] = NULL; } + psi_ffi_struct_type_pad(&els[nels], padding); + nels += padding; + offset += padding; } + ZEND_ASSERT(offset == darg->layout->pos); - ZEND_ASSERT(nels + 1 < argc); + offset = (offset + darg->layout->len + type->alignment - 1) & ~(type->alignment - 1); els[nels++] = type; -//fprintf(stderr, "%s o:%d, a:%d, p:%d l:%d\n", darg->var->name, offset, align, padding, darg->layout->len); - offset += MAX(align, padding) + darg->layout->len; } -//fprintf(stderr, "%s s:%d o=%d\n", strct->name, strct->size, offset); + + /* apply struct alignment padding */ + offset = (offset + maxalign - 1) & ~(maxalign - 1); + ZEND_ASSERT(offset <= strct->size); if (offset < strct->size) { - padding = strct->size - offset; - for (j = 0; j < padding; ++j) { - ffi_type *pad = malloc(sizeof(*pad)); - - ZEND_ASSERT(nels + 1 < argc); - memcpy(pad, &ffi_type_schar, sizeof(*pad)); - els[nels++] = pad; - } + psi_ffi_struct_type_pad(&els[nels], strct->size - offset); } return els; @@ -186,7 +191,7 @@ static inline ffi_type *psi_ffi_decl_type(decl_type *type) { ffi_type *strct = calloc(1, sizeof(ffi_type)); strct->type = FFI_TYPE_STRUCT; - strct->size = 0;//real->strct->size; + strct->size = 0; strct->elements = psi_ffi_struct_type_elements(real->strct); real->strct->engine.type = strct; diff --git a/src/libjit.c b/src/libjit.c index 6d55e1a..dd84394 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -74,49 +74,53 @@ static void psi_jit_struct_type_dtor(void *type) { jit_type_free(strct); } + +static size_t psi_jit_struct_type_pad(jit_type_t **els, size_t padding) { + size_t i; + + for (i = 0; i < padding; ++i) { + *els++ = jit_type_copy(jit_type_sys_char); + } + + return padding; +} + static unsigned psi_jit_struct_type_elements(decl_struct *strct, jit_type_t **fields) { - size_t i, j, argc = strct->args->count << 2, nels = 0, offset = 0, align, padding; - *fields = calloc(argc, sizeof(*fields)); + size_t i, j, argc = strct->args->count, nels = 0, offset = 0, maxalign; + *fields = calloc(argc + 1, sizeof(*fields)); for (i = 0; i < strct->args->count; ++i) { decl_arg *darg = strct->args->args[i]; jit_type_t type = jit_type_copy(psi_jit_decl_arg_type(darg)); + size_t padding, alignment; - if (darg->layout->pos > offset) { - padding = darg->layout->pos - offset; - align = ((padding - 1) | (jit_type_get_alignment(type) - 1)) + 1; - if (align >= padding) { - padding = 0; - } - } else { - align = 0; - padding = 0; - } + ZEND_ASSERT(jit_type_get_size(type) == darg->layout->len); - if (padding) { - for (j = 0; j < padding; ++j) { - jit_type_t pad = jit_type_copy(jit_type_sys_char); + if ((alignment = jit_type_get_alignment(type)) > maxalign) { + maxalign = alignment; + } - ZEND_ASSERT(nels + 1 < argc); - (*fields)[nels++] = pad; + if ((padding = psi_offset_padding(darg->layout->pos - offset, alignment))) { + if (nels + padding > argc) { + argc += padding; + *fields = realloc(*fields, (argc + 1) * sizeof(*fields)); } + psi_jit_struct_type_pad(&(*fields)[nels], padding); + nels += padding; + offset += padding; } + ZEND_ASSERT(offset == darg->layout->pos); - ZEND_ASSERT(nels + 1 < argc); + offset = (offset + darg->layout->len + alignment - 1) & ~(alignment - 1); (*fields)[nels++] = type; - - offset += MAX(align, padding) + darg->layout->len; } + /* apply struct alignment padding */ + offset = (offset + maxalign - 1) & ~(maxalign - 1); + ZEND_ASSERT(offset <= strct->size); if (offset < strct->size) { - padding = strct->size - offset; - for (j = 0; j < padding; ++j) { - jit_type_t pad = jit_type_copy(jit_type_sys_char); - - ZEND_ASSERT(nels + 1 < argc); - (*fields)[nels++] = pad; - } + nels += psi_jit_struct_type_pad(&(*fields)[nels], strct->size - offset); } return nels; diff --git a/src/module.c b/src/module.c index 3e95970..5a44593 100644 --- a/src/module.c +++ b/src/module.c @@ -108,6 +108,15 @@ size_t psi_t_align(token_t t, size_t s) return ((s - 1) | (a - 1)) + 1; } +size_t psi_offset_padding(size_t diff, size_t alignment) +{ + if (diff && diff <= ((diff - 1) | (alignment -1)) + 1) { + diff = 0; + } + + return diff; +} + int psi_internal_type(impl_type *type) { switch (type->type) { -- 2.30.2