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])
)
])
+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, [
)
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
])
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.
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)
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);
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)) {
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;
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;
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;
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) {