@@ -3420,4 +3420,117 @@ static void ZEND_FASTCALL zend_jit_zval_ffi_obj(zval *zv, zend_ffi_type *type, v
34203420 ZVAL_OBJ (zv , & cdata -> std );
34213421 }
34223422}
3423+
3424+ static zend_ffi_cdata * ZEND_FASTCALL zend_jit_zval_ffi_addr (zval * zv )
3425+ {
3426+ zend_ffi_cdata * cdata , * new_cdata ;
3427+ zend_ffi_type * type , * new_type ;
3428+
3429+ if (Z_TYPE_P (zv ) == IS_INDIRECT ) {
3430+ zv = Z_INDIRECT_P (zv );
3431+ }
3432+ ZVAL_DEREF (zv );
3433+ ZEND_ASSERT (Z_TYPE_P (zv ) == IS_OBJECT );
3434+
3435+ cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
3436+ type = ZEND_FFI_TYPE (cdata -> type );
3437+
3438+ // if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER
3439+ // && cdata->ptr == &cdata->ptr_holder) {
3440+ // zend_throw_error(zend_ffi_exception_ce, "FFI::addr() cannot create a reference to a temporary pointer");
3441+ // return NULL;
3442+ // }
3443+
3444+ new_type = emalloc (sizeof (zend_ffi_type ));
3445+ new_type -> kind = ZEND_FFI_TYPE_POINTER ;
3446+ new_type -> attr = 0 ;
3447+ new_type -> size = sizeof (void * );
3448+ new_type -> align = _Alignof(void * );
3449+ /* life-time (source must relive the resulting pointer) ??? */
3450+ new_type -> pointer .type = type ;
3451+
3452+ new_cdata = emalloc (sizeof (zend_ffi_cdata ));
3453+ // inlined zend_ffi_object_init()
3454+ GC_SET_REFCOUNT (& new_cdata -> std , 1 );
3455+ GC_TYPE_INFO (& new_cdata -> std ) = GC_OBJECT | (IS_OBJ_DESTRUCTOR_CALLED << GC_FLAGS_SHIFT );
3456+ new_cdata -> std .extra_flags = 0 ;
3457+ new_cdata -> std .ce = zend_ffi_api -> cdata_ce ;
3458+ new_cdata -> std .handlers = zend_ffi_api -> cdata_ce -> default_object_handlers ; /* zend_ffi_cdata_handlers */
3459+ new_cdata -> std .properties = NULL ;
3460+ zend_objects_store_put (& new_cdata -> std );
3461+ new_cdata -> type = ZEND_FFI_TYPE_MAKE_OWNED (new_type );
3462+ new_cdata -> flags = 0 ;
3463+
3464+ new_cdata -> ptr = (void * )& new_cdata -> ptr_holder ;
3465+ new_cdata -> ptr_holder = cdata -> ptr ;
3466+
3467+ return new_cdata ;
3468+ }
3469+
3470+ static zend_ffi_cdata * ZEND_FASTCALL zend_jit_zval_ffi_addr_var (zval * zv )
3471+ {
3472+ zend_ffi_cdata * cdata , * new_cdata ;
3473+ zend_ffi_type * type , * new_type ;
3474+ zval * arg = zv ;
3475+
3476+ if (Z_TYPE_P (zv ) == IS_INDIRECT ) {
3477+ zv = Z_INDIRECT_P (zv );
3478+ }
3479+ ZVAL_DEREF (zv );
3480+ ZEND_ASSERT (Z_TYPE_P (zv ) == IS_OBJECT );
3481+
3482+ cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
3483+ type = ZEND_FFI_TYPE (cdata -> type );
3484+
3485+ // if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER
3486+ // && cdata->ptr == &cdata->ptr_holder) {
3487+ // zend_throw_error(zend_ffi_exception_ce, "FFI::addr() cannot create a reference to a temporary pointer");
3488+ // return NULL;
3489+ // }
3490+
3491+ new_type = emalloc (sizeof (zend_ffi_type ));
3492+ new_type -> kind = ZEND_FFI_TYPE_POINTER ;
3493+ new_type -> attr = 0 ;
3494+ new_type -> size = sizeof (void * );
3495+ new_type -> align = _Alignof(void * );
3496+ /* life-time (source must relive the resulting pointer) ??? */
3497+ new_type -> pointer .type = type ;
3498+
3499+ new_cdata = emalloc (sizeof (zend_ffi_cdata ));
3500+ // inlined zend_ffi_object_init()
3501+ GC_SET_REFCOUNT (& new_cdata -> std , 1 );
3502+ GC_TYPE_INFO (& new_cdata -> std ) = GC_OBJECT | (IS_OBJ_DESTRUCTOR_CALLED << GC_FLAGS_SHIFT );
3503+ new_cdata -> std .extra_flags = 0 ;
3504+ new_cdata -> std .ce = zend_ffi_api -> cdata_ce ;
3505+ new_cdata -> std .handlers = zend_ffi_api -> cdata_ce -> default_object_handlers ; /* zend_ffi_cdata_handlers */
3506+ new_cdata -> std .properties = NULL ;
3507+ zend_objects_store_put (& new_cdata -> std );
3508+ new_cdata -> type = ZEND_FFI_TYPE_MAKE_OWNED (new_type );
3509+ new_cdata -> flags = 0 ;
3510+
3511+ new_cdata -> ptr = (void * )& new_cdata -> ptr_holder ;
3512+ new_cdata -> ptr_holder = cdata -> ptr ;
3513+
3514+ if (Z_REFCOUNTED_P (arg )) {
3515+ zend_refcounted * ref = Z_COUNTED_P (arg );
3516+
3517+ if (!GC_DELREF (ref )) {
3518+ if (ref == (zend_refcounted * )cdata || GC_REFCOUNT (& cdata -> std ) == 1 ) {
3519+ if (ZEND_FFI_TYPE_IS_OWNED (cdata -> type )) {
3520+ /* transfer type ownership */
3521+ cdata -> type = type ;
3522+ new_type -> pointer .type = ZEND_FFI_TYPE_MAKE_OWNED (type );
3523+ }
3524+ if (cdata -> flags & ZEND_FFI_FLAG_OWNED ) {
3525+ /* transfer ownership */
3526+ cdata -> flags &= ~ZEND_FFI_FLAG_OWNED ;
3527+ new_cdata -> flags |= ZEND_FFI_FLAG_OWNED ;
3528+ }
3529+ }
3530+ rc_dtor_func (ref );
3531+ }
3532+ }
3533+
3534+ return new_cdata ;
3535+ }
34233536#endif
0 commit comments