diff options
Diffstat (limited to 'Zend/zend_types.h')
-rw-r--r-- | Zend/zend_types.h | 111 |
1 files changed, 65 insertions, 46 deletions
diff --git a/Zend/zend_types.h b/Zend/zend_types.h index b381eeff14..d77fbc68a3 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -106,87 +106,106 @@ typedef void (*copy_ctor_func_t)(zval *pElement); * It shouldn't be used directly. Only through ZEND_TYPE_* macros. * * ZEND_TYPE_IS_SET() - checks if type-hint exists - * ZEND_TYPE_IS_MASK() - checks if type-hint refer to standard type + * ZEND_TYPE_IS_ONLY_MASK() - checks if type-hint refer to standard type * ZEND_TYPE_IS_CLASS() - checks if type-hint refer to some class * ZEND_TYPE_IS_CE() - checks if type-hint refer to some class by zend_class_entry * * ZEND_TYPE_IS_NAME() - checks if type-hint refer to some class by zend_string * * * ZEND_TYPE_NAME() - returns referenced class name * ZEND_TYPE_CE() - returns referenced class entry - * ZEND_TYPE_MASK() - returns MAY_BE_* type mask + * ZEND_TYPE_PURE_MASK() - returns MAY_BE_* type mask + * ZEND_TYPE_FULL_MASK() - returns MAY_BE_* type mask together with other flags * * ZEND_TYPE_ALLOW_NULL() - checks if NULL is allowed * - * ZEND_TYPE_ENCODE_*() should be used for construction. + * ZEND_TYPE_INIT_*() should be used for construction. */ -typedef uintptr_t zend_type; - -#define _ZEND_TYPE_CODE_MAX ((Z_L(1)<<(IS_VOID+1))-1) -#define _ZEND_TYPE_FLAG_MASK Z_L(0x3) -#define _ZEND_TYPE_CE_BIT Z_L(0x1) +typedef struct { + /* Not using a union here, because there's no good way to initialize them + * in a way that is supported in both C and C++ (designated initializers + * are only supported since C++20). */ + void *ptr; + uint32_t type_mask; + /* TODO: We could use the extra 32-bit of padding on 64-bit systems. */ +} zend_type; + +#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 24 +#define _ZEND_TYPE_MASK ((1u << 24) - 1) +#define _ZEND_TYPE_MAY_BE_MASK ((1u << (IS_VOID+1)) - 1) +#define _ZEND_TYPE_CE_BIT (1u << 22) +#define _ZEND_TYPE_NAME_BIT (1u << 23) /* Must have same value as MAY_BE_NULL */ -#define _ZEND_TYPE_NULLABLE_BIT Z_L(0x2) +#define _ZEND_TYPE_NULLABLE_BIT 0x2 #define ZEND_TYPE_IS_SET(t) \ - ((t) != 0) - -#define ZEND_TYPE_IS_MASK(t) \ - ((t) != 0 && (t) <= _ZEND_TYPE_CODE_MAX) + (((t).type_mask & _ZEND_TYPE_MASK) != 0) #define ZEND_TYPE_IS_CLASS(t) \ - ((t) > _ZEND_TYPE_CODE_MAX) + (((t.type_mask) & (_ZEND_TYPE_NAME_BIT|_ZEND_TYPE_CE_BIT)) != 0) #define ZEND_TYPE_IS_CE(t) \ - (((t) & _ZEND_TYPE_CE_BIT) != 0) + (((t.type_mask) & _ZEND_TYPE_CE_BIT) != 0) #define ZEND_TYPE_IS_NAME(t) \ - (ZEND_TYPE_IS_CLASS(t) && !ZEND_TYPE_IS_CE(t)) + (((t.type_mask) & _ZEND_TYPE_NAME_BIT) != 0) + +#define ZEND_TYPE_IS_ONLY_MASK(t) \ + (ZEND_TYPE_IS_SET(t) && (t).ptr == NULL) #define ZEND_TYPE_NAME(t) \ - ((zend_string*)((t) & ~_ZEND_TYPE_FLAG_MASK)) + ((zend_string *) (t).ptr) + +#define ZEND_TYPE_LITERAL_NAME(t) \ + ((const char *) (t).ptr) #define ZEND_TYPE_CE(t) \ - ((zend_class_entry*)((t) & ~_ZEND_TYPE_FLAG_MASK)) + ((zend_class_entry *) (t).ptr) -#define ZEND_TYPE_MASK(t) \ - (t) +#define ZEND_TYPE_SET_PTR(t, _ptr) \ + ((t).ptr = (_ptr)) + +/* FULL_MASK() includes the MAY_BE_* type mask, the CE/NAME bits, as well as extra reserved bits. + * The PURE_MASK() only includes the MAY_BE_* type mask. */ +#define ZEND_TYPE_FULL_MASK(t) \ + ((t).type_mask) + +#define ZEND_TYPE_PURE_MASK(t) \ + ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK) + +#define ZEND_TYPE_FULL_MASK_WITHOUT_NULL(t) \ + ((t).type_mask & ~_ZEND_TYPE_NULLABLE_BIT) + +#define ZEND_TYPE_PURE_MASK_WITHOUT_NULL(t) \ + ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK & ~_ZEND_TYPE_NULLABLE_BIT) #define ZEND_TYPE_CONTAINS_CODE(t, code) \ - (((t) & (1 << (code))) != 0) + (((t).type_mask & (1u << (code))) != 0) #define ZEND_TYPE_ALLOW_NULL(t) \ - (((t) & _ZEND_TYPE_NULLABLE_BIT) != 0) - -#define ZEND_TYPE_WITHOUT_NULL(t) \ - ((t) & ~_ZEND_TYPE_NULLABLE_BIT) + (((t).type_mask & _ZEND_TYPE_NULLABLE_BIT) != 0) -#define ZEND_TYPE_ENCODE_NONE() \ - (0) +#define ZEND_TYPE_INIT_NONE(extra_flags) \ + { NULL, (extra_flags) } -#define ZEND_TYPE_ENCODE_MASK(maybe_code) \ - (maybe_code) +#define ZEND_TYPE_INIT_MASK(_type_mask) \ + { NULL, (_type_mask) } -#define ZEND_TYPE_ENCODE_CODE(code, allow_null) \ - (((code) == _IS_BOOL ? (MAY_BE_FALSE|MAY_BE_TRUE) : (1 << (code))) \ - | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0))) +#define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags) \ + ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? (MAY_BE_FALSE|MAY_BE_TRUE) : (1 << (code))) \ + | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags)) -#define ZEND_TYPE_ENCODE_CE(ce, allow_null) \ - (((uintptr_t)(ce)) | _ZEND_TYPE_CE_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0))) +#define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \ + { (void *) (_ce), \ + _ZEND_TYPE_CE_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } -#define ZEND_TYPE_ENCODE_CLASS(class_name, allow_null) \ - (((uintptr_t)(class_name)) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0))) +#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \ + { (void *) (class_name), \ + _ZEND_TYPE_NAME_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } -#define ZEND_TYPE_ENCODE_CLASS_CONST_0(class_name) \ - ((zend_type) class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_1(class_name) \ - ((zend_type) "?" class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_Q2(macro, class_name) \ - macro(class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) \ - ZEND_TYPE_ENCODE_CLASS_CONST_Q2(ZEND_TYPE_ENCODE_CLASS_CONST_ ##allow_null, class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST(class_name, allow_null) \ - ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) +#define ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, extra_flags) \ + { (void *) (class_name), \ + _ZEND_TYPE_NAME_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } typedef union _zend_value { zend_long lval; /* long value */ |