X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Flibffi.c;h=e30966aeb3a4e635eb6fedb3a314a328338cbc17;hp=d01d907d36db2ded651f2eaaa8ee0c4336ff236d;hb=b029005e56a8913fbb3d17ab497b4a37a00a211c;hpb=53495ef4bd0321f7f92dd05eef8e01b90d7b415a diff --git a/src/libffi.c b/src/libffi.c index d01d907..e30966a 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -105,6 +105,11 @@ static void psi_ffi_prep_va(ffi_cif *base, ffi_cif *signature, size_t argc, size assert(FFI_OK == rc); } +#if HAVE_INT128 +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); static inline ffi_type *psi_ffi_token_type(token_t t) { @@ -130,13 +135,16 @@ static inline ffi_type *psi_ffi_token_type(token_t t) { return &ffi_type_sint64; case PSI_T_UINT64: return &ffi_type_uint64; +#if HAVE_INT128 + case PSI_T_INT128: + return ffi_type_sint128; + case PSI_T_UINT128: + return ffi_type_uint128; +#endif case PSI_T_BOOL: return &ffi_type_uchar; - case PSI_T_INT: case PSI_T_ENUM: return &ffi_type_sint; - case PSI_T_LONG: - return &ffi_type_slong; case PSI_T_FLOAT: return &ffi_type_float; case PSI_T_DOUBLE: @@ -217,7 +225,7 @@ static ffi_type **psi_ffi_struct_type_elements(struct psi_decl_struct *strct) { maxalign = type->alignment; } - assert(type->size == darg->layout->len); + assert(type->size <= darg->layout->len); if ((padding = psi_offset_padding(darg->layout->pos - offset, type->alignment))) { if (nels + padding + 1 > argc) { argc += padding; @@ -529,6 +537,73 @@ static inline void psi_ffi_impl_dtor(struct psi_impl *impl) { } } +static void psi_ffi_extvar_get(ffi_cif *sig, void *result, void **args, void *data) { + struct psi_decl_extvar *evar = data; + + psi_decl_extvar_get(evar, result); +} + +static void psi_ffi_extvar_set(ffi_cif *sig, void *result, void **args, void *data) { + struct psi_decl_extvar *evar = data; + + psi_decl_extvar_set(evar, args[0]); +} + +struct psi_ffi_extvar_info { + struct { + ffi_cif signature; + void *code; + ffi_closure *closure; + } get; + struct { + ffi_cif signature; + ffi_type *params[1]; + void *code; + ffi_closure *closure; + } set; +}; + +static inline ffi_status psi_ffi_extvar_init(struct psi_decl_extvar *evar, + ffi_type *type) { + struct psi_ffi_extvar_info *info = calloc(1, sizeof(*info)); + ffi_status rc; + + rc = ffi_prep_cif(&info->get.signature, FFI_DEFAULT_ABI, 0, + type, NULL); + if (FFI_OK != rc) { + return rc; + } + rc = psi_ffi_prep_closure(&info->get.closure, &info->get.code, + &info->get.signature, psi_ffi_extvar_get, evar); + if (FFI_OK != rc) { + return rc; + } + + info->set.params[0] = type; + rc = ffi_prep_cif(&info->set.signature, FFI_DEFAULT_ABI, 1, + &ffi_type_void, info->set.params); + if (FFI_OK != rc) { + return rc; + } + rc = psi_ffi_prep_closure(&info->set.closure, &info->set.code, + &info->set.signature, psi_ffi_extvar_set, evar); + if (FFI_OK != rc) { + return rc; + } + + evar->info = info; + evar->getter->sym = info->get.code; + evar->setter->sym = info->set.code; + + return FFI_OK; +} + +static inline void psi_ffi_extvar_dtor(struct psi_decl_extvar *evar) { + if (evar->info) { + free(evar->info); + evar->info = NULL; + } +} static inline struct psi_ffi_context *psi_ffi_context_init(struct psi_ffi_context *L) { ffi_status rc; @@ -569,6 +644,14 @@ static void psi_ffi_dtor(struct psi_context *C) } } + if (C->vars) { + size_t i = 0; + struct psi_decl_extvar *evar; + + while (psi_plist_get(C->vars, i++, &evar)) { + psi_ffi_extvar_dtor(evar); + } + } if (C->impls) { size_t i = 0; struct psi_impl *impl; @@ -583,35 +666,42 @@ static void psi_ffi_dtor(struct psi_context *C) static zend_function_entry *psi_ffi_compile(struct psi_context *C) { - size_t i = 0, d = 0, nf = 0; + size_t i = 0, d = 0, v = 0, nf = 0; struct psi_impl *impl; struct psi_decl *decl; - zend_function_entry *zfe; + struct psi_decl_extvar *evar; + zend_function_entry *zfe = NULL; - if (!C->impls) { - return NULL; + while (psi_plist_get(C->vars, v++, &evar)) { + ffi_type *type = psi_ffi_decl_arg_type(evar->arg); + + if (FFI_OK == psi_ffi_extvar_init(evar, type)) { + /* */ + } } - zfe = calloc(psi_plist_count(C->impls) + 1, sizeof(*zfe)); + if (C->impls) { + zfe = calloc(psi_plist_count(C->impls) + 1, sizeof(*zfe)); - while (psi_plist_get(C->impls, i++, &impl)) { - zend_function_entry *zf = &zfe[nf]; + while (psi_plist_get(C->impls, i++, &impl)) { + zend_function_entry *zf = &zfe[nf]; - if (!impl->decl) { - continue; - } - if (!psi_ffi_decl_init(impl->decl)) { - continue; - } - if (!psi_ffi_impl_init(impl, C)) { - continue; - } + if (!impl->decl) { + continue; + } + if (!psi_ffi_decl_init(impl->decl)) { + continue; + } + if (!psi_ffi_impl_init(impl, C)) { + continue; + } - zf->fname = impl->func->name + (impl->func->name[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); - ++nf; + zf->fname = impl->func->name + (impl->func->name[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); + ++nf; + } } while (psi_plist_get(C->decls, d++, &decl)) { @@ -701,7 +791,43 @@ static void *psi_ffi_query(struct psi_context *C, enum psi_context_query q, void return NULL; } +static ZEND_RESULT_CODE psi_ffi_load() +{ +#if HAVE_INT128 + ffi_type *i128, *u128; + + i128 = calloc(1, 3*sizeof(ffi_type)); + i128->type = FFI_TYPE_STRUCT; + i128->size = 0; + i128->elements = (ffi_type **) (i128 + 1); + i128->elements[0] = &ffi_type_sint64; + i128->elements[1] = &ffi_type_sint64; + + ffi_type_sint128 = i128; + + u128 = calloc(1, 3*sizeof(ffi_type)); + u128->type = FFI_TYPE_STRUCT; + u128->size = 0; + u128->elements = (ffi_type **) (u128 + 1); + u128->elements[0] = &ffi_type_uint64; + u128->elements[1] = &ffi_type_uint64; + + ffi_type_uint128 = u128; +#endif + return SUCCESS; +} + +static void psi_ffi_free() +{ +#if HAVE_INT128 + free(ffi_type_sint128); + free(ffi_type_uint128); +#endif +} + static struct psi_context_ops ops = { + psi_ffi_load, + psi_ffi_free, psi_ffi_init, psi_ffi_dtor, psi_ffi_compile,