struct member fixes
authorMichael Wallner <mike@php.net>
Tue, 26 Jan 2016 07:40:37 +0000 (08:40 +0100)
committerMichael Wallner <mike@php.net>
Tue, 26 Jan 2016 07:40:37 +0000 (08:40 +0100)
m4/psi.m4
m4/psi_struct.m4
m4/psi_type.m4
php_psi.h
src/context.c
src/libffi.c
src/libjit.c
src/module.c

index 3853fa6..37864d0 100644 (file)
--- 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_<TYPE>
+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_<TYPE>
+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, [
index fcee59c..5a03dd5 100644 (file)
@@ -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
 ])
 
index 2936ef1..7e4badb 100644 (file)
@@ -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_<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)
index 8bac826..7673d4e 100644 (file)
--- 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);
index 3ab1d21..0242b77 100644 (file)
@@ -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)) {
index d59712c..5962b5e 100644 (file)
@@ -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;
index 6d55e1a..dd84394 100644 (file)
@@ -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;
index 3e95970..5a44593 100644 (file)
@@ -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) {