administrativa
[m6w6/ext-psi] / src / libffi.c
index 99f5c5fe2adfa129d6e82ee5936c5fbbcd6b3634..30210cf5b329762d6c44e7c8121291159d60ed1c 100644 (file)
@@ -137,8 +137,7 @@ static ffi_type *ffi_type_sint128;
 static ffi_type *ffi_type_uint128;
 #endif
 
-static inline ffi_type *psi_ffi_decl_arg_type(struct psi_decl_arg *darg,
-               struct psi_decl *fn);
+static inline ffi_type *psi_ffi_decl_arg_type(struct psi_decl_arg *darg);
 
 static inline ffi_type *psi_ffi_token_type(token_t t) {
        switch (t) {
@@ -219,7 +218,7 @@ 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));
+               ffi_type *pad = pemalloc(sizeof(*pad), 1);
 
                memcpy(pad, &ffi_type_schar, sizeof(*pad));
                *els++ = pad;
@@ -238,9 +237,10 @@ struct psi_ffi_struct_element_storage {
 };
 
 static inline void psi_ffi_struct_type_element(
-               struct psi_ffi_struct_element_storage *s, struct psi_decl_arg *darg) {
+               struct psi_ffi_struct_element_storage *s, struct psi_decl_arg *darg,
+               ffi_type *darg_type) {
 
-       ffi_type *type, **tmp;
+       ffi_type *type;
        size_t padding;
 
        if (darg->layout->pos == s->last_arg_pos) {
@@ -249,8 +249,8 @@ static inline void psi_ffi_struct_type_element(
        }
        s->last_arg_pos = darg->layout->pos;
 
-       type = malloc(sizeof(*type));
-       *type = *psi_ffi_decl_arg_type(darg, NULL);
+       type = pemalloc(sizeof(*type), 1);
+       *type = *darg_type;
 
        if (type->alignment > s->max_align) {
                s->max_align = type->alignment;
@@ -260,13 +260,7 @@ static inline void psi_ffi_struct_type_element(
        if ((padding = psi_offset_padding(darg->layout->pos - s->offset, type->alignment))) {
                if (s->nels + padding + 1 > s->argc) {
                        s->argc += padding;
-                       tmp = realloc(s->els, (s->argc + 1) * sizeof(*s->els));
-                       if (tmp) {
-                               s->els = tmp;
-                       } else {
-                               free(s->els);
-                               abort();
-                       }
+                       s->els = safe_perealloc(s->els, (s->argc + 1), sizeof(*s->els), 0, 1);
                        s->els[s->argc] = NULL;
                }
                psi_ffi_struct_type_pad(&s->els[s->nels], padding);
@@ -281,16 +275,15 @@ static inline void psi_ffi_struct_type_element(
 
 static ffi_type **psi_ffi_struct_type_elements(struct psi_decl_struct *strct) {
        size_t i = 0;
-       ffi_type **tmp;
        struct psi_decl_arg *darg;
        struct psi_ffi_struct_element_storage s = {0};
 
        s.last_arg_pos = -1;
        s.argc = psi_plist_count(strct->args);
-       s.els = calloc(s.argc + 1, sizeof(*s.els));
+       s.els = pecalloc(s.argc + 1, sizeof(*s.els), 1);
 
        while (psi_plist_get(strct->args, i++, &darg)) {
-               psi_ffi_struct_type_element(&s, darg);
+               psi_ffi_struct_type_element(&s, darg, psi_ffi_decl_arg_type(darg));
        }
 
        /* apply struct alignment padding */
@@ -300,13 +293,7 @@ static ffi_type **psi_ffi_struct_type_elements(struct psi_decl_struct *strct) {
        if (s.offset < strct->size) { /* WTF? */
                size_t padding = strct->size - s.offset;
 
-               tmp = realloc(s.els, (padding + s.argc + 1) * sizeof(*s.els));
-               if (tmp) {
-                       s.els = tmp;
-               } else {
-                       free(s.els);
-                       return NULL;
-               }
+               s.els = safe_perealloc(s.els, (padding + s.argc + 1), sizeof(*s.els), 0, 1);
                psi_ffi_struct_type_pad(&s.els[s.nels], padding);
                s.els[s.argc + padding] = NULL;
        }
@@ -324,7 +311,7 @@ static inline ffi_type *psi_ffi_decl_type(struct psi_decl_type *type) {
        switch (real->type) {
        case PSI_T_STRUCT:
                if (!real->real.strct->engine.type) {
-                       ffi_type *strct = calloc(1, sizeof(ffi_type));
+                       ffi_type *strct = pecalloc(1, sizeof(ffi_type), 1);
 
                        strct->type = FFI_TYPE_STRUCT;
                        strct->size = 0;
@@ -340,7 +327,7 @@ static inline ffi_type *psi_ffi_decl_type(struct psi_decl_type *type) {
                {
                        struct psi_decl_arg *arg;
                        psi_plist_get(real->real.unn->args, 0, &arg);
-                       return psi_ffi_decl_arg_type(arg, NULL);
+                       return psi_ffi_decl_arg_type(arg);
                }
 
        default:
@@ -354,32 +341,56 @@ static inline ffi_type *psi_ffi_decl_func_array_type(struct psi_decl *fn) {
        struct psi_ffi_decl_info *info = fn->info;
        struct psi_ffi_struct_element_storage s = {0};
        struct psi_layout l;
+       ffi_type *type;
        size_t i;
 
+       if (info->rv_array) {
+               return info->rv_array;
+       }
+
        s.last_arg_pos = -1;
        s.argc = fn->func->var->array_size;
-       s.els = calloc(s.argc + 1, sizeof(*s.els));
+       s.els = pecalloc(s.argc + 1, sizeof(*s.els), 1);
+
+       info->rv_array = pecalloc(1, sizeof(ffi_type), 1);
+       info->rv_array->type = FFI_TYPE_STRUCT;
+       info->rv_array->size = 0;
+       info->rv_array->elements = s.els;
 
-       assert(!fn->func->layout);
        l.pos = 0;
-       l.len = psi_decl_arg_get_size(fn->func);
+       if (fn->func->var->pointer_level > 1) {
+               l.len = SIZEOF_VOID_P;
+               type = &ffi_type_pointer;
+       } else {
+               l.len = psi_decl_type_get_size(fn->func->type, NULL);
+               type = psi_ffi_decl_type(fn->func->type);
+       }
 
+       assert(!fn->func->layout);
        fn->func->layout = &l;
-       psi_ffi_struct_type_element(&s, fn->func);
+       for (i = 0; i < fn->func->var->array_size; ++i) {
+               psi_ffi_struct_type_element(&s, fn->func, type);
+               info->rv_array->elements = s.els;
+               l.pos += l.len;
+       }
        fn->func->layout = NULL;
 
-       info->rv_array = calloc(1, sizeof(ffi_type));
-       info->rv_array->type = FFI_TYPE_STRUCT;
-       info->rv_array->size = 0;
-       info->rv_array->elements = s.els;
-
        return info->rv_array;
 }
 
-static inline ffi_type *psi_ffi_decl_arg_type(struct psi_decl_arg *darg,
-               struct psi_decl *fn) {
+static inline ffi_type *psi_ffi_decl_arg_type(struct psi_decl_arg *darg) {
        if (darg->var->pointer_level) {
-               if (darg->var->array_size && fn) {
+               return &ffi_type_pointer;
+       } else {
+               return psi_ffi_decl_type(darg->type);
+       }
+}
+
+static inline ffi_type *psi_ffi_decl_func_type(struct psi_decl *fn) {
+       struct psi_decl_arg *darg = fn->func;
+
+       if (darg->var->pointer_level) {
+               if (darg->var->array_size) {
                        /* mimic a struct resembling the array return type of fn */
                        return psi_ffi_decl_func_array_type(fn);
                }
@@ -389,15 +400,15 @@ static inline ffi_type *psi_ffi_decl_arg_type(struct psi_decl_arg *darg,
        }
 }
 
-static inline ffi_abi psi_ffi_abi(const char *convention) {
+static inline ffi_abi psi_ffi_abi(zend_string *convention) {
        if (FFI_LAST_ABI - 2 != FFI_FIRST_ABI) {
 #ifdef HAVE_FFI_STDCALL
-               if (!strcasecmp(convention, "stdcall")) {
+               if (zend_string_equals_literal(convention, "stdcall")) {
                        return FFI_STDCALL;
                }
 #endif
 #ifdef HAVE_FFI_FASTCALL
-               if (!strcasecmp(convention, "fastcall")) {
+               if (zend_string_equals_literal(convention, "fastcall")) {
                        return FFI_FASTCALL;
                }
 #endif
@@ -410,17 +421,17 @@ static inline struct psi_ffi_decl_info *psi_ffi_decl_init(struct psi_decl *decl)
                int rc;
                size_t i, c = psi_plist_count(decl->args);
                struct psi_decl_arg *arg;
-               struct psi_ffi_decl_info *info = calloc(1, sizeof(*info) + 2 * c * sizeof(void *));
+               struct psi_ffi_decl_info *info = pecalloc(1, sizeof(*info) + 2 * c * sizeof(void *), 1);
 
                decl->info = info;
 
                for (i = 0; psi_plist_get(decl->args, i, &arg); ++i) {
-                       info->params[i] = psi_ffi_decl_arg_type(arg, NULL);
+                       info->params[i] = psi_ffi_decl_arg_type(arg);
                }
                info->params[c] = NULL;
 
                rc = ffi_prep_cif(&info->signature, psi_ffi_abi(decl->abi->convention),
-                               c, psi_ffi_decl_arg_type(decl->func, decl), info->params);
+                               c, psi_ffi_decl_func_type(decl), info->params);
 
                if (FFI_OK != rc) {
                        free(info);
@@ -483,7 +494,7 @@ static inline void psi_ffi_callback_init(struct psi_ffi_impl_info *impl_info,
                        decl_info = psi_ffi_decl_init(cb->decl);
                }
 
-               cb_info = calloc(1, sizeof(*cb_info));
+               cb_info = pecalloc(1, sizeof(*cb_info), 1);
                cb_info->impl_info = impl_info;
                cb_info->let_exp = let_exp;
                rc = psi_ffi_prep_closure(&cb_info->closure, &cb_info->code,
@@ -561,7 +572,7 @@ static inline void psi_ffi_callback_dtor(struct psi_let_exp *let_exp) {
 static inline struct psi_ffi_impl_info *psi_ffi_impl_init(struct psi_impl *impl,
                struct psi_context *C) {
        struct psi_ffi_context *context = C->context;
-       struct psi_ffi_impl_info *info = calloc(1, sizeof(*info));
+       struct psi_ffi_impl_info *info = pecalloc(1, sizeof(*info), 1);
        struct psi_let_stmt *let;
        ffi_status rc;
        size_t l = 0;
@@ -628,8 +639,7 @@ struct psi_ffi_extvar_info {
 };
 
 static inline ffi_status psi_ffi_extvar_init(struct psi_decl_extvar *evar) {
-       struct psi_ffi_extvar_info *info = calloc(1, sizeof(*info));
-       ffi_type *type;
+       struct psi_ffi_extvar_info *info = pecalloc(1, sizeof(*info), 1);
        ffi_status rc;
 
        evar->info = info;
@@ -637,10 +647,8 @@ static inline ffi_status psi_ffi_extvar_init(struct psi_decl_extvar *evar) {
        psi_ffi_decl_init(evar->getter);
        psi_ffi_decl_init(evar->setter);
 
-       type = psi_ffi_decl_arg_type(evar->arg, evar->getter);
-
        rc = ffi_prep_cif(&info->get.signature, FFI_DEFAULT_ABI, 0,
-                       type, NULL);
+                       psi_ffi_decl_func_type(evar->getter), NULL);
        if (FFI_OK != rc) {
                return rc;
        }
@@ -650,7 +658,7 @@ static inline ffi_status psi_ffi_extvar_init(struct psi_decl_extvar *evar) {
                return rc;
        }
 
-       info->set.params[0] = type;
+       info->set.params[0] = psi_ffi_decl_arg_type(evar->arg);
        rc = ffi_prep_cif(&info->set.signature, FFI_DEFAULT_ABI, 1,
                        &ffi_type_void, info->set.params);
        if (FFI_OK != rc) {
@@ -679,7 +687,7 @@ static inline struct psi_ffi_context *psi_ffi_context_init(struct psi_ffi_contex
        ffi_status rc;
 
        if (!L) {
-               L = malloc(sizeof(*L));
+               L = pemalloc(sizeof(*L), 1);
        }
        memset(L, 0, sizeof(*L));
 
@@ -749,7 +757,7 @@ static zend_function_entry *psi_ffi_compile(struct psi_context *C)
        }
 
        if (C->impls) {
-               zfe = calloc(psi_plist_count(C->impls) + 1, sizeof(*zfe));
+               zfe = pecalloc(psi_plist_count(C->impls) + 1, sizeof(*zfe), 1);
 
                while (psi_plist_get(C->impls, i++, &impl)) {
                        zend_function_entry *zf = &zfe[nf];
@@ -764,7 +772,7 @@ static zend_function_entry *psi_ffi_compile(struct psi_context *C)
                                continue;
                        }
 
-                       zf->fname = impl->func->name + (impl->func->name[0] == '\\');
+                       zf->fname = impl->func->name->val + (impl->func->name->val[0] == '\\');
                        zf->handler = ((struct psi_ffi_impl_info *) impl->info)->code;
                        zf->num_args = psi_plist_count(impl->func->args);
                        zf->arg_info = psi_internal_arginfo(impl);
@@ -864,7 +872,7 @@ static ZEND_RESULT_CODE psi_ffi_load()
 #if HAVE_INT128
        ffi_type *i128, *u128;
 
-       i128 = calloc(1, 3*sizeof(ffi_type));
+       i128 = pecalloc(1, 3*sizeof(ffi_type), 1);
        i128->type = FFI_TYPE_STRUCT;
        i128->size = 0;
        i128->elements = (ffi_type **) (i128 + 1);
@@ -873,7 +881,7 @@ static ZEND_RESULT_CODE psi_ffi_load()
 
        ffi_type_sint128 = i128;
 
-       u128 = calloc(1, 3*sizeof(ffi_type));
+       u128 = pecalloc(1, 3*sizeof(ffi_type), 1);
        u128->type = FFI_TYPE_STRUCT;
        u128->size = 0;
        u128->elements = (ffi_type **) (u128 + 1);